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     });

 

posted @ 2019-02-07 23:45  紫诺花开  阅读(383)  评论(0编辑  收藏  举报