隔壁小孩都饞哭的vue組件傳值講解

寫在前面:

我是一個堅持學習的技術小白,在博客裏分享自己的學習總結記錄,如果你也在努力變成更好的自己,可以關注我,一起加油!
如果任何問題或交友,歡迎各位與我聯繫:[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 解構到當前頁面的方式讓代碼更優雅

最後


以上爲本人的一點學習記錄與總結,如有錯誤,請指出,不勝感激。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章