父组件使用子组件时,自定义属性(属性名任意,属性值为要传递的数据)
子组件通过props接收父组件数据,通过自定义属性的属性名
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <child_temp v-bind:child_msg="parent_msg" :chlid_movies="parent_movies"></child_temp> </div> <template id="child_temp"> <div> <ul> <li v-for="item in chlid_movies">{{item}}</li> </ul> <p>{{child_msg}}</p> <p>{{chlid_movies}}</p> <p>{{myname}}</p> <!--<button @click="child_btn">子按钮</button>--> </div> </template> </body> <script src="../../js/vue.js"></script> <script> const child_temp = { template:'#child_temp', /*props:['chlid_movies','child_msg'],*/ props:{ //props的扩展,包括类型,默认值,是否必须等 //1类型限制 /*chlid_movies:Array, child_msg:String*/ //2.提供默认值,扩展 chlid_movies:{ type:Array, default() { return []; } }, child_msg: { type: String, required: true, default() { //如果把child_temp模板里的v-bind:child_msg="parent_msg"去掉,页面就会显示这里的值 return ["子_我是子组件默认值,当使用父组件data里的属性值得时候,如果没有用v-bind绑定,会取到我这一串值"]; } }/*, methods:{ child_btn(){ alert("我是子组件的方法") } }*/ }, data(){ return { myname:"子_我是子属性自己的值,我使用的是自己组件里的data的属性值" } } } var vm = new Vue({ el:"#app", data:{ parent_msg:"父_我是父组件里的信息,传到了子组件", parent_movies:['父_火影','父_海贼王','父_柯南'] }, components:{ child_temp } }) </script> </html>
效果:
props:定义需要从父组件中接收的属性
items:是要接收的属性名称
type:限定父组件传递来的必须是数组
default:默认值
required:是否必须
验证支持的数据类型
String
Number
Boolean
Array
Object
Date
Function
Symbol
动态静态传递
给 prop 传入一个静态的值:
<temp child_msg="大家好,我是组件"/>
给 prop 传入一个动态的值: (通过v-bind从数据模型中,获取title的值)
<temp :child_msg="parent_msg"/>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--父组件模板--> <div id="app"> <!--监听子组件发射出的btn_child_click事件,find_parent_click要在父组件里定义methods--> <chlid_temp v-on:btn_child_click="find_parent_click"></chlid_temp> </div> <!--子组件模板--> <template id="chlid_temp"> <div> <button v-for="item in movies" @click="btn_ckik(item)"> {{item.id}}-{{item.name}} </button> </div> </template> </body> <script src="../../js/vue.js"></script> <script> //子组件 const chlid_temp = { template:"#chlid_temp", data(){ return{ movies:[ {id:"1",name:"火影"}, {id:"2",name:"海贼"}, {id:"3",name:"七大罪"}, {id:"4",name:"菜鸟java是怎么炼成的"}, {id:"5",name:"菜鸟是怎么变菜的"}, ] } }, methods:{ btn_ckik(ev){ //自定义事件 this.$emit("btn_child_click",ev) } } } //父组件 var vm = new Vue({ el:"#app", data:{ msg:"我是父组件的信息-msg" }, components:{ chlid_temp }, methods:{ find_parent_click(ev){ console.log(ev) console.log(ev.id +" "+ev.name) } } }); </script> </html>
效果:
需求:父组件里的num1和num2,和子组件里的num1和num2实现双向绑定,并且input1里的num1输入后input2里num2的值会相应的变为num1值得100倍,反之num2是num1的100分之1.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <temp :c_num1="p_num1" :c_num2="p_num2" @data_cnum1_change="parent_cnum1_change" @data_cnum2_change="parent_cnum2_change" ></temp> </div> <template id="temp"> <div> <h3>props:{{c_num1}}</h3> <h3>data:{{data_cnum1}}</h3> <!--<input type="text" v-model="data_cnum1">--> input1:<input type="text" :value="data_cnum1" @input="num1_input"> <h3>props:{{c_num2}}</h3> <h3>data:{{data_cnum2}}</h3> <!--<input type="text" v-model="data_cnum2">--> <!--<input type="text" :value="data_cnum2" @input="data_cnum2=$event.target.value">--> input2:<input type="text" :value="data_cnum2" @input="num2_input"> </div> </template> </body> <script src="../../js/vue.js"></script> <script> const temp={ template:"#temp", props:{ c_num1:Number, c_num2:Number }, data(){ return{ data_cnum1:this.c_num1, data_cnum2:this.c_num2 } }, methods:{ num1_input(e){ //1 将input的value赋值到data_cnum1上 this.data_cnum1 = e.target.value; //2 为了让父组件可以改值,发出一个事件 this.$emit("data_cnum1_change",this.data_cnum1); //3 同事修改data_cnum2的值(data_cnum2的值是data_cnum1的100倍) this.data_cnum2 = this.data_cnum1 * 100; this.$emit("data_cnum2_change",this.data_cnum2) }, num2_input(e){ this.data_cnum2 = e.target.value; this.$emit("data_cnum2_change",this.data_cnum2); //(data_cnum2的值是data_cnum1的100分之一倍) this.data_cnum1 = this.data_cnum2 / 100; this.$emit("data_cnum1_change",this.data_cnum1) } } } var vm = new Vue({ el:"#app", data:{ p_num1:1, p_num2:0 }, components:{ temp }, methods:{ parent_cnum1_change(data_cnum1){ //默认传过来的是Strnig类型,需要转换成number console.log(typeof data_cnum1) this.p_num1 = parseInt(data_cnum1); }, parent_cnum2_change(data_cnum2){ this.p_num2 = parseInt(data_cnum2); } } }) </script> </html>
父访问子使用使用$children或$refs
$children的缺陷:通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs$refs的使用:$refs和ref指令通常是一起使用的。首先,我们通过ref给某一个子组件绑定一个特定的ID。其次,通过this.$refs.ID就可以访问到该组件了。
例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <cpn></cpn> <cpn></cpn> <cpn></cpn> <cpn ref="ref_name"></cpn> <button @click="btnClick">按钮</button> {{message}} </div> <template id="cpn"> <div>我是子组件</div> </template> <script src="../../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊' }, methods: { btnClick() { // 1.$children console.log(this.$children); for (let v of this.$children) { console.log(v.child_name); v.childMessage(); this.message = v.child_name; } console.log(this.$children[3].child_name+'================'); /*console.log(this.$children[4].child_name+'++++++++++++');*/ // 2.$refs => 对象类型, 默认是一个空的对象 ref='ref-name' console.log(this.$refs.ref_name.child_name+"----------"); } }, components: { cpn: { template: '#cpn', data() { return { child_name: '我是子组件的name哈哈' } }, methods: { childMessage() { console.log('childMessage'); } } }, } }) </script> </body> </html>
$parent
子访问父<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <button @click="rootclik()">根组件按钮</button> <cpn></cpn> </div> <template id="cpn"> <div> <h2>我是cpn组件</h2> <ccpn></ccpn> </div> </template> <template id="ccpn"> <div> <h2>我是子组件</h2> <button @click="btnClick">按钮</button> </div> </template> <script src="../../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '我是ccpn组件的根组件的name' }, methods: { rootclik(){ console.log("我是根组件root的事件") } }, components: { cpn: { template: '#cpn', data() { return { name: '我是ccpn组件的父组件的name' } }, methods: { parentclik(){ console.log("我是父组件parent的事件") } }, components: { ccpn: { template: '#ccpn', methods: { btnClick() { // 1.访问父组件$parent console.log("======parent start============") console.log(this.$parent); console.log(this.$parent.name); console.log(this.$parent.parentclik()); console.log("======parent end============") // 2.访问根组件$root console.log("======root start============") console.log(this.$root); console.log(this.$root.message); console.log(this.$root.rootclik()); console.log("======root end============") } } } } } } }) </script> </body> </html>