寫在前面:
我是一個堅持學習的技術小白,在博客裏分享自己的學習總結記錄,如果你也在努力變成更好的自己,可以關注我,一起加油!
如果任何問題或交友,歡迎各位與我聯繫:[email protected]
正文
vue組件化
組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器爲它添加特殊功能。在有些情況下,組件也可以表現爲用 js 特性進行了擴展的原生 HTML 元素。
父子組件傳值
在 Vue 中,父子組件的關係可以總結爲:prop 向下傳遞, 事件($emit) 向上傳遞。父組件通過 prop 給子組件下發數據,子組件通過 事件 給父組件發送消息。
注意:
父組件可以向子組件傳遞數據,傳遞過來的數據可以隨意修改,但子組件不能隨意修改父組件傳遞過來的數據,比如說:父組件向好幾個子組件傳遞相同的數據,其中一個子組件修改值,因爲接受到的是引用類型的數據,所以一個組件修改值,可能導致其他子組件引用修改的數據。這也是 Vue 官網提到的 單向數據流的概念。Vue 官網描述
父組件向子組件傳值
父組件中需要進行的操作:
- import 子組件
- 註冊 import 的子組件
- 使用子組件的地方,v-bind (綁定)要傳遞的屬性值
//parent.vue
<template>
<div id="app">
<h3>我是父組件</h3>
<!-- 子組件, 綁定父組件要傳遞給子組件的值 -->
<childCom :child="msg"></childCom>
</div>
</template>
<script>
import childCom from "./child"; //引入子組件
export default {
components: { //註冊子組件
childCom
},
data() {
return {
msg: "哈哈哈"
};
}
};
</script>
子組件中接收父組件的值:
- 使用 props 接收傳遞的值,props 是一個數組,比如:props:[“child”] , 數組裏面的元素都是父組件傳遞過來的屬性名,接收後可以當 data 中定義的屬性一樣使用,比如:{{child}}
- props 還可以使用對象方式接收,並設置類型,比如:props:{“child” : {type : String}},其中 type 是該屬性值的類型,強調傳遞的值是 String 類型,它會進行驗證,如果不是 String 類型,會報錯。還可以設置 屬性值的默認值,寫法:props : {“child” : {type : String, default = “嘿嘿”}}
// child.vue
<template>
<div>
<h3>我是子組件</h3>
<div>{{child}}</div>
</div>
</template>
<script>
export default {
//接收從父組件傳遞的值
props: ["child"]
};
</script>
結果展示:
子組件向父組件傳值
父組件中需要進行的操作:
- 在父組件中 import 子組件,註冊子組件,使用子組件並v-bind 屬性值
- 使用子組件時 v-on 綁定方法名
- 父組件中定義綁定的方法,此方法名要與 v-on 綁定的方法名一致
// parent.vue
<template>
<div id="app">
<h3>我是父組件</h3>
<!-- 使用子組件,綁定屬性值與方法 -->
<childCom :child="msg" @passMethods="passMethod"></childCom>
</div>
</template>
<script>
import childCom from "./child"; //引入子組件
export default {
//註冊子組件
components: {
childCom
},
data() {
return {
msg: "哈哈哈"
};
},
methods: {
//子組件中綁定的方法
passMethod(data) {
this.msg = data;
}
}
};
</script>
子組件向父組件傳遞值:
- 用 emit 向父組件傳遞值,比如:this.$emit(“passMethods”, “修改父組件的msg”); 第一個參數是父組件中綁定的事件(@passMethods),這兩個名字一定要相同,第二個參數是傳遞的值
- 子組件標籤中綁定 emit 的方法
// child.vue
<template>
<div>
<h3>我是子組件</h3>
<!-- 插值表達式,顯示傳遞的值 -->
<div>{{child}}</div>
<br />
<!-- 按鈕,點擊事件綁定方法 -->
<el-button @click="passMethods">點擊,子組件傳遞值給父組件</el-button>
</div>
</template>
<script>
export default {
//接收從父組件傳遞的值
props: ["child"],
methods: {
// 點擊事件綁定方法
passMethods() {
this.$emit("passMethods", "修改父組件的msg");
}
}
};
</script>
結果展示:
兄弟組件間傳值
兄弟組件的概念是什麼?圖中組件分爲了三層,上面講解的是 1 與 2 進行傳值,那兄弟組件就是 3 和 3 之間傳值。那我們是不是需要 3-2-1-2-3,這種方式進行傳遞呢?答案是可以實現,但也太麻煩了吧!
打個比方:老師當作父組件,學生當作子組件,考試的時候,學生的筆壞了,想向旁邊的同學借筆,這時候,學生舉手說:老師,我想借根筆。老師會拿旁邊同學的筆給他。如果兄弟組件可以傳值,就不用老師進行傳遞了,兩個同學可以獨立完成借筆這個操作。這也就是:觀察者模式(也叫發佈訂閱模式/總線模式/Bus)
<body>
<div id="root">
<!-- 聲明兩個子組件 -->
<child content='點贊收藏關注一條龍'></child>
<child content='不可能只點贊收藏'></child>
<script src="./vue.js"></script>
</div>
<script type="text/javascript">
// 給每個vue實例添加 bus 屬性,起到總線的作用
Vue.prototype.bus = new Vue()
// 聲明全局子組件,名爲 child
Vue.component('child',{
data:function(){
return {
childContent:this.content
}
},
props:{
content:String
},
// click事件綁定handleclick方法
template:'<div @click="handleclick">{{childContent}}</div>',
methods:{
handleclick:function(){
// 子組件向外觸發 change 事件,攜帶content值
this.bus.$emit('change',this.content)
}
},
mounted:function(){
var vm=this;
// 組件掛載時,觸發聲明週期鉤子mounted,用於監聽 change 事件,接收傳遞的值
this.bus.$on('change',function(msg){
vm.childContent=msg;
})
}
})
//新建vue實例進行掛載
var vm=new Vue({
el:'#root'
})
</script>
</body>
結果展示:
我們來捋一遍整個過程如何實現的?:
我們點擊文字,觸發組件內的 handleclick 事件,handleclick 事件向總線觸發 ‘change’ 事件,並將值傳遞過去。兩個子組件被掛載完成時,都會執行 mounted 函數鉤子,將各自組件保存在變量 vm 中,然後監聽的 ‘change’ 事件被觸發,將事件攜帶的值,傳遞給各自子組件的值。點擊的文字的值傳遞過去,值不變;未點擊的文字的值傳遞過去,改變了。這樣,就實現了組件間傳值。
不相關組件間傳值
使用 vuex 進行傳值,在 vue 項目中安裝插件 vuex 插件。
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
至於如何使用 vuex 進行傳值呢?
A頁面向B頁面傳值。
- A頁面將值存儲到 store.js 中
- B從 store.js 中進行讀取
//A頁面將數據存儲到 store.js 中
this.$store.commit("setAData", this.data); // 存儲當前數據
//store.js 文件中進行接收
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
//接收A頁面傳遞的數據
setAData(state, data) {
state.data = data;
},
}
})
//B頁面讀取 store.js 中的數據
//寫法一
computed:{
getAData(){
return this.$store.state.data
}
},
//寫法二
import { mapState } from "vuex"; // 引入vuex用於將全局變量映射爲頁面變量
computed:{
...mapState([ //解構到計算屬性中
'data' //store.js 中的數據
])
},
//寫法三
import { mapState } from "vuex"; // 引入vuex用於將全局變量映射爲頁面變量
computed:{
...mapState([ //解構到計算屬性中
Bdata:'data' //重命名
])
},
注意:
- 官方建議我們將 this.$store.state.xxx 放到計算屬性中使用,可以讓代碼看起來更優雅。
- 每次讀取 store.js 中的數據時,不需要用 this.$store.state.xxx 這種方式進行讀取,使用寫法二 …mapState 解構到當前頁面的方式讓代碼更優雅
最後
以上爲本人的一點學習記錄與總結,如有錯誤,請指出,不勝感激。