vue 组件数据传递
vue组件化开发
主要为了把一个大功能拆分成若干个小的功能,解决高耦合问题,同时也方便开发人员维护。
从功能上组件可以分为木偶组件和功能组件。
木偶组件(为了接收数据,渲染数据,基本上是没有逻辑的,越往下越木偶)
功能组件(更多是控制数据,有大量的逻辑,越往顶层越功能)
组件化开发的优势:
1、提高开发效率
2、方便重复使用
3、便于协同开发
4、更容易管理维护
写法 :
Vue.component(组件名称,对象){}
命名规则:
定义组件名的方式有两种
1)短横线方式 my-component
2)首字母大写方式 MyComponent
但是在HTML模板中尽量使用短横线方式
关于组件的几个注意事项:
1、必须放在根实例(new Vue)的上面
2、组件名字与引入组件的名字尽量保持一致
3、template顶层只能有一个div盒子
4、在子组件中,data必须为函数,函数值返回一个对象,对象下面挂数据
父级传递子级
首先在子组件上加一个v-bind:自定义属性,等于父级的数据
//比如<ppx v-bind:data="arr"></ppx> //简写<ppx :data="arr">
子组件通过props来接收数据
//props:['data']
最后使用即可
//{{data}}
注意:
自定义属性不要和子组件数据名称一样
props可以为数字,数组时候传字符串
props可以为对象,为了启用高级配置(传入数据类型的检测和设置默认值)
一般使用对象形式
<div id="app"> <!-- arr 是父组件的--> <ppx :data="arr"></ppx> </div>
1 let obj = { 2 props:['data'], 3 template:` 4 <ul> 5 <li v-for="(val,key) in data"> 6 {{val}} 7 </li> 8 </ul> 9 `, 10 data(){ 11 return { 12 val:'我是子组件' 13 } 14 } 15 } 16 17 Vue.component('ppx',obj); 18 new Vue({ 19 el:'#app', 20 data:{ 21 arr:[111,222,333] 22 } 23 });
子级传递父级
在子组件上绑定一个自定义事件,并且传入父级的“事件”处理函数
比如 子组件定义<ppx @customev="changC">,其中changC是父组件定义的
在子组件内部监听这个自定义事件,this.$emit('自定义事件名',参数)
比如
1 change(){ 2 this.$emit('customev',id,xxx) 3 }
vue 组件间传递数据为单向数据流动:
父级把数据传给子级,子级拿到数据后渲染页面,但无权修改父组件传递给它的数据
(父组件通过 props 向下传递数据给子组件,子组件通过 $emit触发父组件的自定义事件 给父组件发送消息)
数据从父级流向子级,数据本身还是父级的。
如果操作子级要改变父级的数据,只能通过子级告知父级要操作哪个数据
然后让父级去修改自己的数据,修改完毕再传给子级
比如checkbox复选框,修改他只能让父级修改,不允许子级修改
<div id="app"> <h2>父组件</h2> <input type="text" v-model="val" @keyup.13="add" > {{arr}} <h4>子组件</h4> <ppx :data="arr" @changebool="ck"></ppx> </div>
1 let obj={ 2 props:{ 3 data:{ 4 type:Array, 5 default:[] 6 } 7 }, 8 template:` 9 <div> 10 <ul> 11 <li v-for="(val,key) in data"> 12 <input type="checkbox" @click="changeC(val.id,$event)"> 13 <span>{{val.name}}</span> 14 </li> 15 </ul> 16 </div> 17 `, 18 methods:{ 19 changeC(id,ev){ 20 //自定义的changebool事件,触发时候执行ck 21 this.$emit('changebool',id,ev.target.checked); 22 } 23 } 24 } 25 Vue.component('ppx',obj); 26 new Vue({ 27 el:'#app', 28 data:{ 29 val:'', 30 arr:[ 31 { 32 id:0, 33 name:'巴黎', 34 checked:false 35 }, 36 { 37 id:1, 38 name:'东京', 39 checked:false 40 }, 41 { 42 id:2, 43 name:'伦敦', 44 checked:true 45 }, 46 { 47 id:3, 48 name:'悉尼', 49 checked:false 50 } 51 ] 52 }, 53 methods:{ 54 add(){ 55 this.arr.push({ 56 id:+new Date,//隐式类型转换,可以把字符串转成数字类型 57 name:this.val, 58 checked:false 59 }); 60 this.val = ''; 61 }, 62 ck(id,bool){ 63 this.arr.forEach(e=>{ 64 //如果当前的id 等于 id 就把当前数据的checked 赋给 bool 65 if(e.id === id){ 66 e.checked = bool; 67 } 68 }) 69 } 70 } 71 });
另一种方法
如果要让子级有功能(操作父级数据的能力),那么可以把父级传进来的数据变成自己的
子级改变自己的数据,是不会影响父级的数据
注意:
如果父级传进来的数据是复合类型(引用类型)的,那么变成自己的数据时,要深拷贝一下,不然改变子级会影响父级
<div id="app"> <h2>父级的</h2> <input type="text" v-model="val" @keyup.13="add"> {{arr}} <hr> <h2>子组件</h2> <list :data="arr" :k="kk" @getchilddata="changeC"></list> </div>
1 let obj = { 2 template:` 3 <div> 4 <ul> 5 <li v-for="(val,key) in cd"> 6 <input 7 type="checkbox" 8 @change="changeFn(val.id)" 9 > 10 <span>{{val.txt}}</span> 11 </li> 12 </ul> 13 {{cd}} 14 </div> 15 `, 16 methods:{ 17 changeFn(id){ 18 let b; 19 this.cd.forEach(data => { 20 if(data.id === id){ 21 data.checked = !data.checked; 22 b = data.checked; 23 } 24 }); 25 26 this.$emit('getchilddata',id,b); 27 console.log(this.cd); 28 29 } 30 }, 31 props:['data','k'], 32 data(){ 33 return { 34 cd:JSON.parse(JSON.stringify(this.data)) 35 } 36 } 37 } 38 39 Vue.component('list',obj); 40 41 new Vue({ 42 el:'#app', 43 data:{ 44 kk:'变', 45 val:'', 46 arr:[ 47 { 48 id:0, 49 txt:'小明', 50 checked:false 51 }, 52 { 53 id:1, 54 txt:'小红', 55 checked:false 56 }, 57 { 58 id:2, 59 txt:'小刚', 60 checked:false 61 } 62 ] 63 } 64 ,methods:{ 65 add(){ 66 this.arr.push({ 67 id: +new Date, 68 txt:this.val, 69 checked:false 70 }); 71 this.val = ''; 72 }, 73 changeC(id,bool){ 74 this.arr.forEach(e=>{ 75 if(e.id === id){ 76 e.checked = bool; 77 }; 78 }); 79 } 80 } 81 });