一、組件傳值
1.父組件向子組件傳值
因為子組件本身不能拿到父組件的data數據來用,所以在子組件里用props接收,props是一個數組
父組件向子組件傳值 <div id="app"> <com1 :parent="msg" :parentarr="arr"></com1> </div> <template id="com"> <div> {{parent}} <ul> <li v-for="i in parentarr">{{i}}</li> </ul> </div> </template> <script src="lib/vue-2.4.0.js"></script> <script type="text/javascript"> var vm=new Vue({ el:"#app", data:{ msg:"父組件的msg", arr:[1,2,3], }, components:{ com1:{ template:"#com", props:["parent",'parentarr'],//父組件向子組件傳值,用props } } }) </script>
2.子組件向父組件傳值
子組件不能直接使用父組件的data和methods,子組件向父組件傳值用 @和$emit實現(通過函數的形式傳出,在父組件接收)
做法:
在父組件里定義一個@xxx="xxx2"的方法,父組件把方法傳遞給子組件,this.$emit()的第一個參數和xxx的名稱一樣,父元素的方法xxx2傳一個實參進去就相當於是當前傳回來的值
this.$emit("fun1",this.xxx) 方法名字/要傳出的值
子組件向父組件傳值 <div id="app1"> <com-name @fun1="getData"></com-name> </div> <template id="com2"> <div> <button @click="getsonData">調用父組件的getdata</button> </div> </template> <script src="lib/vue-2.4.0.js"></script> <script type="text/javascript"> var vm=new Vue({ el:"#app1", data:{ fromson:"" }, methods:{ getData(x){//傳實參 console.log("父元素的方法getdata拿到子組件里的數據是==="+x) this.fromson=x; } }, components:{ comName:{ template:"#com2", data(){ return { sonmsg:"子組件里的msg" } }, methods:{ getsonData(){ this.$emit("fun1",this.sonmsg)//$emit調用fun1 } } }, } }) </script>
二、refs獲取dom節點
Vue不提倡用原生的dom操作獲取節點,它封裝了自己的方法來實現獲取dom
做法:
給要獲取的dom一個ref屬性,起一個名字,通過this.$refs來得到組件里所有有ref屬性的dom節點,返回的是一個json
<div id="app"> <p ref="p1">父組件里的p</p> <button @click="getCon">獲取內容</button> <com ref="login"></com> </div> <template id="login"> <div> <p>{{sonmsg}}</p> </div> </template> <script src="lib/vue.js"></script> <script> Vue.component("com",{ template:"#login", data(){ return { sonmsg:"子組件的msg" } }, }) var vm=new Vue({ el:"#app", methods:{ getCon(){ console.log(this.$refs.login.sonmsg)//子組件的msg console.log(this.$refs.p1.innerHTML)//父組件里的p } } }) </script>
那么,子組件向父組件傳值就有倆種方法
①用@和$emit
②組件也可以有ref屬性,可以通過組件的ref屬性拿到子組件的data和method
三、插槽 (slot)
插槽是將父組件中的子組件模板數據正常顯示出來
假設組件的名稱為child
1.插槽的概念
child組件開標簽和閉標簽之間的內容正常不會顯示在頁面中,如果想要讓他顯示,用slot標簽代表這些內容,想要讓她在哪兒顯示就放在模板的哪個位置
理解插槽:
組件就相當於是封裝的html 那么插槽就相當於是封裝函數里的參數,是每次調用時候都可以賦不同的值的東西
2.具名插槽(傳遞name屬性)
給放在child開標簽和閉標簽之間的模板或者組件加上v-slot:自定義名字 的指令,在用的時候使用slot標簽,在子組件中的 <slot><slot> 里面添加 name='自定義名字' ,通過name屬性選擇調用哪個插槽。如果父組件中有一部分沒有添加 slot 屬性,則此處就是默認的插槽,在子組件中的slot直接就是使用的父組件的默認插槽部分
3.后備內容
在<slot></slot>標簽中的內容將在沒有匹配到插槽內容時渲染
4.作用域插槽
插槽雖然是屬於這個組件的,但是因為他沒有放在組件的模板里,所以不能直接使用組件的data數據,如果要想使用組件的data 應該用屬性傳值的方法把數據傳過去 在插槽里通過v-slot:xx="" 等號后面的值接收數據,接收到的數據是一個json 因為有可能傳過來不只一個值
v-slot:xx="yy" xx代表插槽的名字 yy代表接收到組件的data數據
<div id="app"> <child> <template v-slot:head="datas"> <div> <h5>組件child里的頭部模板=={{datas.textcon}}</h5> </div> </template> <template v-slot:foot> <div> <h5>組件child里的尾部模板</h5> </div> </template> <template> <div>我是一個沒有名字的插槽</div> </template> </child> <child> <template v-slot:head> <div> <h4>第二次調用組件child的頭部模板</h4> </div> </template> <template v-slot:foot> <div> <h4>第二次調用組件child的的尾部模板</h4> </div> </template> </child> </div> <template id="login"> <div> <header> <slot name="head" :textcon="text" ></slot> </header> <p>{{text}}</p> <slot>AA</slot> <!-- 后備內容放在slot標簽里,如果插槽沒有傳過來內容的話 默認顯示AA,如果傳過來內容就取代AA --> <footer> <slot name="foot"></slot> </footer> </div> </template> <script src="lib/vue.js"></script> <script> Vue.component("child", { template: "#login", data() { return { text: "子組件的內容", } }, }) var vm = new Vue({ el: "#app", }) </script>