Vue2.0-下篇

来源:互联网 发布:suse网络配置 编辑:程序博客网 时间:2024/06/05 02:30

全局组件

语法糖

在vue中,组件不能继承父级的数据,不能直接使用外围包裹的一些数据

vm实例中,数据存放在data属性。组件中,数据由data()方法返回。使用数据时,均用花括号{{}}解析,如{{name}}、{{msg}}

<div id="app">    <hello></hello></div><script>    //方法一    var et=Vue.extend({        template:'<h1>hello,welcome to wuhan</h1>'    });    //注册组件    Vue.component('hello',et);    //方法二:语法塘    Vue.component('hello',{        template:'<h1>{{msg}},welcome to wuhan</h1>',        // template:'<h1>{{msg}},welcome to {{name}}</h1>'        // 控制台报错: Property or method "name" is not defined on the instance        data(){            return {                msg:'Hello'            }        }    });    var vm=new Vue({        el:'#app',        data:{            name:'hubei'        }    });</script>

局部组件

<div id="app">    <hello></hello></div><script>    //局部组件在实例内部声明,可以有多个    var vm=new Vue({        el:'#app',        components:{            hello:{                template:'<h1>{{name}}</h1>',                data(){                    return {name:'wuhan'}                }            }        }    });</script>

父子组件

<div id="app">    <parent></parent></div><template id="tp">    <div>        <div>parent</div>        <child></child>    </div></template><script>    //局部组件在实例内部声明,可以有多个    var vm=new Vue({        el:'#app',        components:{            parent:{                template:'#tp',                components:{                    child:{                        template:'<div>child</div>'                    }                }            }        }    });</script>

子组件向父组件传递数据

$emit( [自定义事件名] , [传递数据])

点击Child,触发“s”事件,并向事件绑定的方法传递子组件自身的age。parent组件中,@s事件发生后,执行p方法,p(data)将传进来的年龄赋值给父组件自身的age属性。

<div id="app">    <parent></parent></div><template id="tp">    <div>        <div>parent</div>{{age}}        <child @s="p"></child>    </div></template><script>    //局部组件在实例内部声明,可以有多个    var vm=new Vue({        el:'#app',        components:{            parent:{                template:'#tp',                data(){                  return {age:0}                },                methods:{                    p(data){                        this.age=data;                    }                },                components:{                    child:{                        template:'<div @click="sayAge">child</div>',                        data(){                            return {age:18}                        },                        methods:{                            sayAge(){                                //向上发射事件$emit                                this.$emit('s',this.age);                            }                        }                    }                }            }        }    });</script>

父组件向子组件传递数据

1、传:在父组件的模板中,给子组件的n属性动态绑定父组件的name

2、收:在子组件中声明属性n。

方法一:props:[‘n’],数组中添加属性名n即可,来什么收什么。

方法二:props:{ n:String },对象中添加一个键值对key:value,key是属性名,value是属性的数据类型。n:String表示属性n只接收String类型的数据,否则,虽然收到的数据仍会显示出来,但会报错

Invalid prop: type check failed for prop "n". Expected String, got Number.
<div id="app">    <parent></parent></div><template id="tp">    <div>        <div>parent</div>        <child :n="name"></child>    </div></template><script>    //局部组件在实例内部声明,可以有多个    var vm=new Vue({        el:'#app',        components:{            parent:{                template:'#tp',                data(){                    return {                        //name:'Hangzhou'                        name:123                    }                },                components:{                    child:{                        template:'<div>child {{n}}</div>',                        //props:['n']                        //对属性的数据类型进行校验                        props:{n:String}                    }                }            }        }    });</script>

注意

详情见Vue官方文档

HTML是不区分大小写的,deliveryPrice属性在HTML中写为delivery-price

  • goods.vue
<template>    <shopcart :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice"></shopcart></template>
  • shopcart.vue
<script type="text/ecmascript-6">  export default {    props: {      deliveryPrice: String    }  };</script>

子组件改变父组件数据(*)

vue1.0可以,但vue2.0不可以。
在vue2.0中,子组件是不允许更改父组件的

父组件传给子组件的是引用数据类型,此时,两者操作的是同一个地址的数据,达到子组件可以改变父组件数据的效果

<div id="app">    <parent></parent></div><template id="tp">    <div>        <div>parent</div>{{name.name}}        <child :n="name"></child>    </div></template><script>    //局部组件在实例内部声明,可以有多个    var vm=new Vue({        el:'#app',        components:{            parent:{                template:'#tp',                data(){                  //2.0,返回的不再是字符串,而是一个对象,引用数据类型                  return {name:{name:'Hangzhou'}}                },                components:{                    child:{                        template:'<div @click="update">child {{n.name}}</div>',                        methods:{                            update(){                                this.n.name='jw'                            }                        },                        //2.0                        props:{n:Object}                    }                }            }        }    });</script>

对比vue1.0

1.0 只用加sync,就可以将子组件与父组件的数据同步,更改子组件的,父组件也会更改

<div id="app">    <parent></parent></div><template id="tp">    <div>        <div>parent</div>{{name}}        <child :n.sync="name"></child>    </div></template><script src="vue1.0.js"></script><script>    var vm=new Vue({        el:'#app',        components:{            parent:{                template:'#tp',                data(){                  return {name:'Hangzhou'}                },                components:{                    child:{                        template:'<div @click="update">child {{n}}</div>',                        methods:{                            update(){                                this.n='jw'                            }                        },                        //1.0                        props:{n:String}                    }                }            }        }    });</script>

子组件更改,父组件数据不同步

<div id="app">    <parent></parent></div><template id="tp">    <div>        <div>parent</div>        {{name}}        <child :n="name"></child>    </div></template><script src="vue2.0.js"></script><script>    var vm=new Vue({        el:'#app',        components:{            parent:{                template:'#tp',                data(){                    return {name:'Hangzhou'}                },                components:{                    child:{                        template:'<div @click="update">child {{a}}</div>',                        data(){                            return {a:''}                        },                        mounted(){                            this.a=this.n;                        },                        methods:{                            update(){                                this.a='jw'                            }                        },                        props:{n:String}                    }                }            }        }    });</script>

若components这样写(不推荐),如下:

会警告
vue2.0.js:465 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “n”

当父组件重新渲染时,子组件已经更改过的数据会被父组件传递过来的数据覆盖掉,因此推荐使用上一种方法。

components:{    child:{        template:'<div @click="update">child {{n}}</div>',        methods:{            update(){                this.n='jw'            }        },        props:{n:String}    }}

组件的is特性

用于显示特定的组件,当有多个组件,但在特定时刻只需要显示其中的某个时,可以用到组件的is特性。

<div id="app">    <button @click="comp='hello'">显示英文版hello</button>    <button @click="comp='hello1'">显示中文版你好</button>    <component :is="comp"></component></div><template id="hello">    <div>        hello    </div></template><template id="hello1">    <div>        你好    </div></template><script src="vue2.0.js"></script><script>    var vm=new Vue({        el:'#app',        data:{            comp:'hello'        },        components:{            hello:{                template:'#hello'            },            hello1:{                template:'#hello1'            },        }    });</script>

组件slot槽

组件标签中可以插入内容。例如中想要插入其他内容,此时就要用到slot槽,否则即使写入内容,也会被组件template模板中的内容给覆盖掉。

没有名字的slot使用步骤:

  • 1、直接写入内容,如
<hello>我叫小高</hello>
  • 2、组件模板中添加slot标签,如
<template>    hello<slot></slot></template>

具名slot使用步骤:

  • 1、插入的内容添加slot属性,如
<div slot="name">我叫小高</div>
  • 2、组件模板中添加slot标签,并给出name属性,且与上一步中的slot值对应,例如
<template>    hello    <slot name="name"></slot></template>

下面代码显示结果:
- hello
- 今年三岁了
- 我叫小高

<div id="app">    <hello>        <div slot="name">我叫小高</div>        <div slot="age">今年三岁了</div>    </hello></div><!--没有名字的slot 具有名字的slot--><template id="hello">    <div>        <!--slot直接使用,在<hello>标签中插入的内容会自动到插槽中去了-->        <!--没有名字的slot-->        <!--hello <slot></slot>-->        <!--具名slot-->        hello <slot name="age"></slot><slot name="name"></slot>    </div></template><script src="vue2.0.js"></script><script>    var vm=new Vue({        el:'#app',        data:{            comp:'hello'        },        components:{            hello:{                template:'#hello'            },        }    });</script>

非父子组件的交互

发:点击按钮,hello组件触发send方法,send方法调用Event.$emit(‘我饿了’,this.msg),触发了’我饿了’事件,并传递hello组件的msg属性。

收:hello1组件挂载的时候,Event.$on(‘我饿了’,[function(data)])会监听事件,当监听到了’我饿了’事件,则调用回调函数,将接收到的data赋值给hello1组件的msg。

<div id="app">    <hello></hello>    <hello1></hello1></div><template id="hello">    <div>        hello        <button  @click="send">传递数据</button>    </div></template><template id="hello1">    <div>hello1 {{msg}}</div></template><script src="vue2.0.js"></script><script>    //事件a    var Event=new Vue;//event.$on event.$emit    var vm=new Vue({        el:'#app',        components:{            hello:{                template:'#hello',                data(){                    return {msg:'我非常饿'}                },                methods:{                    send(){                        Event.$emit('我饿了',this.msg);                    }                }            },            hello1:{                mounted(){                    //用箭头函数,保证this的指向问题                    Event.$on('我饿了',(data)=>{                        //console.log(this);//this是当前hello1组件,如果不用箭头函数,this为hello组件                        this.msg=data;                        console.log('msg挂载');//每点击一次按钮,都会执行mounted                    });                },                data(){                    console.log("data加载");//只会执行一次,在打开页面的时候                    return {msg:''}                },                template:'#hello1'            },        }    });</script>

路由

后期专题补充说明路由

<head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .router-link-active{            background: wheat;        }    </style></head><body><div id="app">    <router-link to="/home">首页</router-link>    <router-link to="/list">列表页</router-link>    <router-view></router-view></div><script src="vue2.0.js"></script><script src="vue-router2.0.js"></script><script>    //2.0规定,组件必须要有一个根节点    var Home={template:`<div>                            <h1>首页</h1>                            <router-link to="/home/login">登录</router-link>                            <router-link to="/home/reg">注册</router-link>                            <router-view></router-view>             </div>`}    var List={template:`<div>                            <h1>列表</h1>                            <router-link to="/list/news/1">消息1</router-link>                            <router-link to="/list/news/2">消息2</router-link>                            <router-view></router-view>             </div>`}    var router=new VueRouter({        routes:[            //方法一//            {path:'/home',component:{//                    template:'<h1>首页</h1>'//            }},            //方法二            {path:'/home',component:Home                //子路由                children:[                    //children中,路径最前面不能加'/'                    {path:'login',component:{                        template:'<div>登录</div>'                    }},                    {path:'reg',component:{                        template:'<div>注册</div>'                    }}                ]            },            {path:'/list',component:List,                children:[                    {path:'news/:nid',component:{                        template:'<div>消息是{{$route.params.nid}}</div>'                    },                    beforeEnter(to,from,next){                        console.log(to.params.nid);                        //next();//若没有这一步,代码不会继续向下执行,组件就不会继续渲染                    }}                ]            },            {path:'*',component:Home},        ]    })    var vm=new Vue({        router,        el:'#app'    });</script>