vue組件傳值[持續更新]

最後的約定Y 2021-08-15 17:02:15 阅读数:341

本文一共[544]字,预计阅读时长:1分钟~
vue 更新

組件傳值介紹

vue作為現在前端使用的主流框架之一,組件一直是vue的核心部分。起初,我在學習vue的過程中接觸到了組件之間傳值的功能,但是由於在工作中使用較少,對於這一部分沒有深入的認識,導致在開發過程中遇到了一些問題,通過進一步的學習,我了解到了vue組件傳值的方式以及存在兩類不同的組件傳值方式:同級組件之間的傳值、父子組件之間的傳值

1.組件作用

組件作用:用來减少Vue實例(對象)中的代碼量,日後在使用Vue開發過程中,可以根據不同的業務功能將頁面中劃分不同的多個組件,然後多個組件去構建整個頁面的布局,便於日後使用Vue進行開發時頁面管理(可以做到複用組件),方便日後的維護。

2.組件定義

2.1 全局組件注册

全局組件注册給Vue實例對象,定義之後可以在Vue實例的作用範圍內使用該組件

<div id="app">
<!-- 必須給需要綁定的元素,設置選擇器(支持CSS的選擇器,但是我推薦使用ID選擇,容器是唯一) -->
<h2>{{title}}</h2>
<!-- 使用全局注册組件,可以做到複用 -->
<login></login> <login></login> </div>
<!-- 1.先引入框架的支持(VUE文件),推薦比特置body結束標簽的前面(使用的是瀏覽器運行環境
,如果使用NodeJS是另一種引入方式) -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 定義全局組件
Vue.component('login',{
template:'<diu><h2>用戶登陸頁面</h2></diu>' });
let vm = new Vue({
el: '#app',
data: {
title: '組件學習 - 全局組件注册'
}
});
</script>
複制代碼

代碼說明:

  1. Vue.component 用來開發全局組件
  • 參數1:定義組件名稱login
  • 參數2:組件配置 {} template:'' 用來書寫組件的html代碼,template中必須只能存在一個root元素
  1. 使用時需要在Vue實例的作用範圍內根據組件名稱使用全局組件
  2. 如果在注册組件過程中使用,駝峰命名規則組件的方式,在使用組件時,必須將駝峰的所有單詞小寫加入中劃線(-)進行使用,個人不太推薦駝峰。

2.2局部組件注册

局部組件注册將組件注册給對應Vue實例中一個 components屬性 來完成組件注册,這種方式不會對Vue實例造成累加。

<div id="app">
<!-- 必須給需要綁定的元素,設置選擇器(支持CSS的選擇器,但是我推薦使用ID選擇,容器是唯一) -->
<h2>{{title}}</h2>
<login></login>
<register></register>
<user-table></user-table>
</div>
<!-- 第三種方式 -->
<template id="userTemplate">
<diu><h2>用戶列錶頁面</h2></diu>
</template>
<!-- 1.先引入框架的支持(VUE文件),推薦比特置body結束標簽的前面(使用的是瀏覽器運行環境,如果使用NodeJS是另一種引入方式) -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 3.創建VUE對象(ViewModel中間件),數據Model -->
<script>
let reg = {
template: "<diu><h2>用戶注册頁面</h2></diu>",
};
const userTemplate = {
template: "#userTemplate",
};
let vm = new Vue({
el: "#app",
data: {
title: "組件學習 - 局部組件注册",
},
components: {
login: {
//第一種方式:直接定義
template: "<diu><h2>用戶登陸頁面</h2></diu>",
},
register: reg, //第二種方式:定義變量
userTable: userTemplate, //第三種方式:注意我使用了駝峰的方式,脚手架推薦方式
},
});
</script>
複制代碼

3.關於父子組件的生命周期的執行過程,我會在後續增加

  • beforeCreate:組件開始初始化,僅僅注册組件自己事件和生命周期函數

  • created:組件已經注入data/methods/computed相關數據方法

  • beforeMount:將template中指向html編譯Vue模版,此時還沒有完成模版中內容渲染

  • mounted:將template中html編譯模版進行數據渲染並且將渲染完成的數據再內存中形成虛擬dom替換template指向dom

  • beforeUpdate:當組件中data數據發生變化時,會觸發beforeUpdate,此時頁面中數據還是原始數據

  • updated:此時頁面中數據和data屬性一致

  • beforeDestroy:銷毀VUE實例之前觸發方法

  • destroy:VUE實例已經徹底銷毀、監聽進制全部消失

4.組件數據傳遞

20201016164141543.png

4.1(vue3以下組件傳遞)

4.1.1 父-->子(prop)

作用 props用來給組件傳遞相應靜態數據或者動態數據

在子組件裏定義一個props,即props:[msg],msg可以是對象也可以是基本數據類型

4.1.1.1父組件內容

<template>
<div class="parent">
//傳遞的數據 message
<Children :msg="message"></Children>
</div>
</template>
<script>
//引入的組件
import Children from "../components/Children";
export default {
name: "Parent",
components: {
Children,
},
data() {
return {
message: "hello world",
};
},
};
</script>
複制代碼

4.1.1.2子組件內容

 <template>
<section>父組件傳過來的消息是:{{myMsg}}</section>
</template>
<script>
export default {
name: "Children",
components: {},
//通過props接收到的內容
props: ["msg"],
data() {
return {
//可以通過this拿到傳過來的數據
myMsg: this.msg,
};
},
methods: {},
};
</script>
複制代碼

4.1.2子-->父(emit)

這裏需要使用自定義事件,在子組件中使用this.$emit(‘myEvent’) 觸發,然後在父組件中使用@myEvent監聽

4.1.2.1 子組件

 <template>
<section>
<br />
//聲明點擊事件進行傳遞
<div @click="clickme">click me</div>
</section>
</template>
<script>
export default {
name: "Children",
components: {},
data() {
return {
childNum: 0,
};
},
methods: {
clickme() {
// 通過自定義事件addNum把值傳給父組件
this.$emit("addNum", this.childNum++);
},
},
};
</script>
複制代碼

4.1.2.2 父組件

 <template>
<div class="parent">
這裏是計數:{{parentNum}}
//這裏的addNum 是子組件傳遞的時候聲明的時間 也就是子組件 this.$emit("addNum", this.childNum++);
<Children-Com @addNum="getNum"></Children-Com>
</div>
</template>
<script>
import ChildrenCom from "../components/Children";
export default {
name: "Parent",
components: {
ChildrenCom,
},
data() {
return {
parentNum: 0,
};
},
methods: {
// childNum是由子組件傳入的
getNum(childNum) {
this.parentNum = childNum;
},
},
};
</script>
複制代碼

4.1.3兄弟組件傳值(通過第三方聲明bus組件進行相連)

運用自定義事件e m i t的觸發和監聽能力,定義一個公共的事件總線evenBus,通過它作為中間橋梁,我們就可以傳值給任意組件了。而且通過eventBus的使用, 可以加深emit的觸發和監聽能力,定義一個公共的事件eventBus,通過它作為中間橋梁,我們就可以傳值給任意組件了。而且通過eventBus的使用,可以加深emit的理解

4.1.3.1 bus組件

 import Vue from 'vue'
export default new Vue()
複制代碼

4.1.3.2 Children1.vue(第一個兄弟組件)

 <template>
<section>
<div @click="Children1">push message</div>
<br />
</section>
</template>
<script>
//引用bus組件
import eventBus from "./EventBus";
export default {
name: "Children1",
components: {},
data() {
return {
childNum: 0,
};
},
methods: {
Children1() {
// 通過事件總線發送消息
eventBus.$emit("Children1", this.childNum++);
},
},
};
</script>
複制代碼

4.1.3.3 Children2.vue(第二個兄弟組件)

 <template>
<section>children1傳過來的消息:{{msg}}</section>
</template>
<script>
//引用bus組件
import eventBus from "./EventBus";
export default {
name: "Children2",
components: {},
data() {
return {
msg: "",
};
},
mounted() {
// 通過事件總線監聽消息
eventBus.$on("Children1", (children1Msg) => {
this.msg = children1Msg;
});
},
};
</script>
複制代碼

4.1.3.4 把Children1和Children2放到一個組件裏

 <template>
<div class="parent">
<Children1></Children1>
<Children2></Children2>
</div>
</template>
<script>
//引入的兩個兄弟組件 路徑組件改變
import Children1 from "../components/Children1";
import Children2 from "../components/Children2";
export default {
name: "Parent",
components: {
Children1,
Children2,
},
data() {
return {};
},
methods: {},
};
</script>
複制代碼

4.1.4 路由間傳值

使用問號傳值 A頁面跳轉B頁面時使用 this.$router.push(’/B?name=danseek’)

B頁面可以使用 this.$route.query.name 來獲取A頁面傳過來的值

配置的路由如下

//這個就是router裏面index.js的內容
{
path: '/b/:name',
name: 'b',
component: () => import( '../views/B.vue')
}
複制代碼

4.2(vue3以上的組件傳值)

4.2.1父傳子(props)

4.2.1.1 父組件

 <template>
<div class="home">
<div>
<Children :data="num" @fatherNums="shouFun"></Children>
</div>
</div>
</template>
<script>
import { ref } from "vue";
import Children from "../components/children";
export default {
name: "Home",
components: {
Children,
},
setup(props) {
// 父傳子組件
const num = ref(18);
return {
num,
};
},
};
</script>
複制代碼

4.2.1.2 子組件

 <template>
<div>
{{ num }}
</div>
</template>
<script>
//需要引用的ref綁定
import { ref } from "vue";
export default {
props: {
data: Number,
},
setup(props, { emit }) {
//接收也是props
const num = ref(props.data);
return {
num,
};
},
};
</script>
複制代碼

4.2.2 子傳父(emit)

4.2.2.1父組件

 <template>
<div class="home">
<div>
<p>{{nums}}</p>
<Children :data="num" @fatherNums="shouFun"></Children>
</div>
</div>
</template>
<script>
import { ref } from "vue";
//引入的組件
import Children from "../components/children";
export default {
name: "Home",
//是通過components屬性來引入的組件
components: {
Children,
},
setup(props) {
const nums = ref(null);
// 父接子
const shouFun = (val) => {
console.log(val);
nums.value = val;
};
return {
nums,
};
},
};
</script>
複制代碼

4.2.2.2 子組件

 <template>
<div>
<button @click="fatherNum">子傳父</button>
</div>
</template>
<script>
import { ref } from "@vue/reactivity";
export default {
props: {
data: Number,
},
setup(props, { emit }) {
//通過emit和點擊事件傳遞
const fatherNum = () => {
emit("fatherNums", 666);
};
return {
fatherNum,
};
},
};
</script>
複制代碼

總結

組件傳遞優點

props傳遞數據的優點顯而易見、靈活簡單,可以對props數據進行數據計算、數據監聽等處理,十分靈活方便,但這裏單單只是父子一層。

組件傳遞缺點

我們子組件中使用父組件props的時候,如果涉及到一些變量賦值,修改等操作,props被莫名其妙的修改了,連同父組件的數據也被篡改了,這讓我們很疑惑,父組件的props不是不能修改嗎?這裏怎麼變了,

其實在vue中的props能不能改變,這個得分情况。

props如果是基礎數據類型,當改變時,就會拋出錯誤:

20210422221726802.png

當props是引用類型的話,我們修改這個數據的某一個屬性的實話,就可以。

由此我們可以得出結論:子組件雖然不能直接對父組件prop進行重新賦值,但父組件是引用類型的時候,子組件可以修改父組件的props下面的屬性

這就很尷尬了。如果我們設計的初衷就是父組件數據也能同時被修改,這個結果可以接受,如果不希望父組件的數據有變化是,這就是一個嚴重的邏輯bug。這就是props通訊的風險之一。

版权声明:本文为[最後的約定Y]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/08/20210815170211122Q.html