赞
踩
前面学习了Day18——v-model双向绑定,今天学习一下组件化开发
一个完整的页面可以分成多个组件,每一个组件实现特定的功能,而每个组件可以再进行细分,如下:
Vue.extend()
)const cpn = Vue.extend({
template: `
xxxxxxx
`
});
extend()方法要求传入一个参数,这个参数是一个对象,所以用{}
。这个对象通常要求定义一个template属性,template属性的内容就是我们要在DOM渲染出来的东西。
Vue.component()
)Vue.component('xxx', 组件构造器)
component()方法将刚才的组件构造器注册为一个组件,并且给他起一个组件的标签名称。
<body> <div id="app"> <!--3. 使用组件--> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> </div> <script src="../js/vue.js"></script> <script> //1. 创建组件构造器对象 //符号`与单引号,双引号的作用一样,但是它能支持不加‘+’换行 const cpnC = Vue.extend({ template: ` <div> <h2>我是标题</h2> <p>我是内容,哈哈哈哈哈</p> <p>我是内容,呵呵呵呵呵呵</p> </div>`, }); //2.注册组件 Vue.component('my-cpn', cpnC); const app = new Vue({ el: '#app', data: { message: '你好啊', } }) </script> </body>
在vue实例外注册的组件是全局组件,在vue实例内注册的是局部组件。全局组件在所有vue实例管理的区域都能使用,而局部组件只能在 组件注册的vue实例 管理的区域使用。
开发中常用局部组件,而且一般只有一个实例,没有多个实例。
例子:
<body> <div id="app"> <cpn></cpn> <cpn></cpn> <cpn></cpn> <cpn></cpn> </div> <div id="app2"> <cpn></cpn> </div> <script src="../js/vue.js"></script> <script> //1. 创建组件构造器 const cpnC = Vue.extend({ template: ` <div> <h2>我是标题</h2> <p>我是内容,哈哈哈哈啊哈</p> </div> ` }) //2. 注册组件(全局组件:可以在多个Vue实例下面使用) // Vue.component('cpn', cpnC); //怎么注册局部组件呢?答:在vue实例里面注册就是局部组件 const app = new Vue({ el: '#app', data: { message: '你好啊', }, components: { cpn: cpnC,//在vue实例里面注册的是局部组件 } }) const app2 = new Vue({ el: '#app2' }) </script> </body>
在组件构造器里面注册的组件是子组件。 如下:
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是标题2</h2>
<p>我是内容,呵呵呵呵</p>
<cpn1></cpn1>
</div>
`,
components:{
cpn1: cpnC1, //组件构造器1在组件构造器2里面注册,cpn1是子组件
}
})
例子:
<body> <div id="app"> <cpn2></cpn2> </div> <script src="../js/vue.js"></script> <script> //创建第一个组件构造器(子组件) const cpnC1 = Vue.extend({ template: ` <div> <h2>我是标题1</h2> <p>我是内容,哈哈哈哈</p> </div> ` }) //创建第二个组件构造器(父组件) const cpnC2 = Vue.extend({ template: ` <div> <h2>我是标题2</h2> <p>我是内容,呵呵呵呵</p> <cpn1></cpn1> </div> `, components:{ cpn1: cpnC1, //组件构造器1在组件构造器2里面注册,cpn1是子组件 } }) const app = new Vue({ el: '#app', data: { message: '你好啊', }, components: { cpn2: cpnC2, //组件构造器2在Vue实例里面注册 } }) </script> </body>
实际是将组件构造器传入的对象,作为注册组件的第二个参数。如下:{}
中的就是组件构造器本来的内容
Vue.component('cpn1', {
template: `
<div>
<h2>我是标题1</h2>
<p>我是内容,哈哈哈哈</p>
</div>
`
})
通过<script>
标签,type属性必须是text/x-template
,id属性是必须要有的,如下:
<script type="text/x-template" id="cpn">
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
</div>
</script>
定义好模板后,通过id选择器在注册组件里面建立联系
id属性是必须要有的,如下:
<template id="cpn2">
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
</div>
</template>
定义好模板后,通过id选择器在注册组件里面建立联系
<body> <div id="app"> <cpn></cpn> <cpn2></cpn2> </div> <!-- 1. 通过script标签,type必须是text/x-template--> <script type="text/x-template" id="cpn"> <div> <h2>我是标题</h2> <p>我是内容,哈哈哈哈</p> </div> </script> <!-- 2. 通过template标签--> <template id="cpn2"> <div> <h2>我是标题</h2> <p>我是内容,哈哈哈哈</p> </div> </template> <script src="../js/vue.js"></script> <script> //1. 注册一个全局组件 Vue.component('cpn', { template: '#cpn', }) Vue.component('cpn2', { template: '#cpn2', }) const app = new Vue({ el: '#app', data: { message: '你好啊', } }) </script> </body>
组件是一个单独功能模块的封装,因此它应该要有属于自己的数据。组件不能直接访问vue实例里面的data数据,那么组件的数据应该有自己保存的地方。那就是保存在Vue.component中的data中,data必须是一个函数,而且返回的必须是一个对象
总结:组件的data存放在Vue.component()的data中,而且data必须是一个函数,返回的必须是一个对象。
因为组件可以复用,如果data不是一个函数而是一个对象,那么一个组件在多处地方都有使用,在任意一处地方修改了某些值,那么其他地方组件的值也被修改了。而我们进行组件复用,希望的就是每个组件都有自己的数据,其他地方与我相同的组件不能修改我的数据。
图例解释:
总结:组件的data是一个函数,那么每次使用组件的数据,返回的都是属于自己的数据,其他与我相同的组件也不能修改我的数据
目前使用的是局部组件,它在vue实例里组件,所以vue实例是父组件。父组件向子组件通信,关键是在子组件里面使用props属性。props可以是数组(即props: [ ]
),也可以是对象(即props: { }
)。如果是对象,可以做类型限制。
总结:父组件向子组件通信,只需在子组件里面使用props属性,定义变量或者对象 接收父组件传来的值
<body> <div id="app"> <!--<cpn :cmovies="movies" :cmessage="message"></cpn>--> <cpn :cmovies="movies" :cmessage="message"></cpn> </div> <template id="cpn"> <div> <ul> <li v-for="item in cmovies">{{item}}</li> </ul> <p>{{cmessage}}</p> </div> </template> <script src="../js/vue.js"></script> <script> const cpn = { template: '#cpn', //props是数组类型 // props: ['cmovies', 'cmessage'], //props是对象类型 props: { //可以做类型限制 // cmovies: Array, // cmessage: String, cmovies: { type: Array, default(){ //如果变量的类型是一个对象或者数组时,默认值必须是一个函数 return [] } }, cmessage: { type: String, default: 'aaaaaaaa', //如果没有传cmessage,而又要在dom层显示cmessage,那么默认值就是aaaaaaaa required: true, //表示用此组件的时候,必须要把cmessage变量传进来 } } } const app = new Vue({ el: '#app', data: { message: '你好啊', movies: ['海王', '海贼王', '海尔兄弟'], }, components: { cpn } }) </script> </body>
props不支持驼峰标识,在props中定义了驼峰标识格式的变量(比如cInfo),绑定的时候需要使用c-info
总结:在没有用脚手架写vue代码的情况下,尽量不要用驼峰标识书写props属性相关的代码。可以用‘-’、‘_'隔开。
例子:
<body> <div id="app"> <!-- props不支持驼峰标识,在props中定义了驼峰标识格式的变量(比如cInfo),绑定的时候需要使用c-info--> <cpn :c-info="info" :child-my-message="message"></cpn> </div> <template id="cpn"> <div> <h2>{{cInfo}}</h2> <h2>{{childMyMessage}}</h2> </div> </template> <script src="../js/vue.js"></script> <script> const cpn = { template: '#cpn', props: { cInfo: { type: Object, default() { return []; } }, childMyMessage: { type: String, default: '', } } }; const app = new Vue({ el: '#app', data: { info: { name: 'why', age: 12, height: 1.88, }, message: 'aaaaa', }, components: { cpn, } }) </script> </body>
有些时候在子组件发生的事件,要传给父组件,父组件进而根据传来的信息做出对应的处理(比如请求服务器某些数据,然后返回给子组件)
<body> <!--父组件模板--> <div id="app"> <!--注意,这里监听的事件不能使用驼峰命名,不支持--> <!--处理事件的方法默认会将子组件传来的参数接收,不需要在父组件这里显式定义参数接收--> <cpn @item-click="cpnClick"></cpn> </div> <!--子组件模板--> <template id="cpn"> <div> <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button> </div> </template> <script src="../js/vue.js"></script> <script> /** * 子组件向父组件传递信息: * 1.子组件监听发生在自己身上的事件 * 2.子组件定义方法,发射(使用this.$emit('事件名(自定义,不要使用驼峰标识)');) 发生的事件 给父组件 * 3.父组件监听子组件传来的事件(注意不要使用驼峰标识),定义处理事件的方法 * * @type {{template: string, data(): {categories: [{name: string, id: string}, {name: string, id: string}, {name: string, id: string}, {name: string, id: string}]}, methods: {btnClick(*): void}}} */ //1.子组件 const cpn = { template: '#cpn', data(){ return { categories: [ {id: 'aaa', name: '热门推荐'}, {id: 'bbb', name: '手机数码'}, {id: 'ccc', name: '家用家电'}, {id: 'ddd', name: '电脑办公'}, ], } }, methods: { btnClick(item){ this.$emit('item-click', item);//this.$emit是发送事件, 第二个参数传递给父组件使用 } } } //2.父组件 const app = new Vue({ el: '#app', data: { message: '你好啊', }, components: { cpn, }, methods: { cpnClick(item){ console.log(item); } } }) </script> </body>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。