一、组件传值
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直接就是使用的父组件的默认插槽部分
总:在<template>元素上使用v-slot:自定义名字 指令
<template v-slot:header> <div>AAA</div> </template> <header> <slot name="header"></slot> </header>
v-slot 只能添加在<template>上,v-slot的缩写#
<template #header> <div>AAA</div> </template>
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>