一、组件间的通信
组件实例的作用域是孤立的;这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。但是父子组件之间需要通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。
在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。如下图所示:
二、 Prop — 父组件传递数据给子组件
prop 是父组件用来传递数据的一个自定义属性。子组件需要显式地用 props 选项声明 “prop”:
Vue.component('child', { // 声明 props props: ['message'], // 就像 data 一样,prop 可以用在模板内 // 同样也可以在 vm 实例中像 “this.message” 这样使用 template: '<span>{{ message }}</span>' })
(一)简单的传值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <my-div message="今天要下雨" imgsrc="img/img_02.jpg"></my-div> <my-div message="明天要下冰雹" imgsrc="img/img_01.jpg"></my-div> </div> <template id="my_div"> <div> <h1>{{message}}</h1> <img :src="imgsrc" width="200" alt=""> </div> </template> <script src="js/vue.js"></script> <script> // 1. 创建组件 Vue.component('my-div', { template: '#my_div', // 接收父组件传过来的属性值 props: ['message', 'imgsrc'] }); new Vue({ el: '#app', data: { msg: '今天的天气很好!' } }); </script> </body> </html>
注意:HTML 特性不区分大小写。当使用非字符串模版时,prop的名字形式会从 camelCase 转为 kebab-case(短横线隔开)。
(二)父组件传值给子组件,动态绑定
运行结果
(三)Vue中多层组件通信
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <script type="text/javascript" src="../node_modules/vue/dist/vue.js"></script> <body> <div id="app"> <!-- 最外层父组件 --> <!-- <my_com :接收到变为img_p="data发送的img" :接收title_p="data发送的title"></my_com> --> <my_com v-bind:img_p="img" v-bind:title_p="title"></my_com> </div> <template id="t-img"> <img :src="imgsrc"> </template> <template id='t-title'> <h1>{{ titlesrc }}</h1> </template> <template id="myparent"> <div> <!-- <ch_1>:子组件c1接收到的imgsrc="父级件发送来的img_p"></ch_1> --> <ch_1 v-bind:imgsrc="img_p"></ch_1> <!-- <ch_2 :子组件c2接收到的titlesrc="父组件发送过来的title_p"></ch_2> --> <ch_2 v-bind:titlesrc="title_p"></ch_2> </div> </template> <script type="text/javascript"> // 子组件c1实例 let c1 = Vue.extend({ template:'#t-img', props:['imgsrc'] }); // 子组件c2实例 let c2 = Vue.extend({ template:'#t-title', props: ['titlesrc'] }) // 注册父组件 Vue.component('my_com', { props:['img_p', 'title_p'], components:{ 'ch_1':c1, 'ch_2':c2 }, template:'#myparent' }) new Vue({ el:'#app', data:{ title:'今天天气真好', img:'./屏幕快照 2018-10-24 下午3.58.32.png' } }); </script> </body> </html>
实例:
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <!-- vue实例1 --> <div id="app01"> <parent :mess_p="mess" :img_p="img"></parent> </div> <!-- vue实例2 --> <div id="app02"> <parent :mess_p="m" :img_p='i'></parent> </div> <!--子组件1模板--> <template id="template1"> <img :src="c1_img" alt="" width="300px"> </template> <!-- 子组件模板2 --> <template id="template2"> <p>{{c2_mess}}</p> </template> <!-- 父组件模板 --> <template id="parent"> <div> <child1 :c1_img="img_p"></child1> <child2 :c2_mess="mess_p"></child2> </div> </template> <script src="vue.js/vue.js"></script> <script> // 构造子组件1 let child1 = Vue.extend({ template:"#template1", props: ['c1_img'] }); // 构造子组件2 let child2 = Vue.extend({ template:'#template2', props: ['c2_mess'] }) // 注册父组件 Vue.component('parent', { components: { 'child1':child1, 'child2':child2 }, template:'#parent', props:['mess_p', 'img_p'] }); // vue实例1 new Vue({ el:'#app01', data:{ mess:'今天气很好', img:'../../../../Desktop/屏幕快照 2018-10-24 下午10.40.04.png' } }); // vue实例2 new Vue({ el:'#app02', data:{ m:'今天要下雪', i:'./../img/screenshot.png' } }) </script> </body> </html>