Vue 父子组件
P53 组件的基本使用
创建组件构造对象
const cpnC = Vue.extend({ template: ` <div> <h2>Vue组件化的基本使用</h2> </div> ` })
注册组件
Vue.component('my-cpn',cpnC)
组件的使用
<div id="app"> <my-cpn> </div>
高复用性,组件可以在多个项目中使用
P53全局组件和局部组件
全局组件: Vue.extend 注册的组件都为全局组件
局部组件:
const app = new Vue({ el: '#app', data: { }, components: { cpn: cpnC },
在相应的 Vue 实例对象中注册组件,该组件则只对该实例对象起作用
P54父组件和子组件的区别
const cpnC1 = Vue.extend({ template: ` <div> <h2>注册内容一</h2> </div> ` })
注册两个组件
const cpnC1 = Vue.extend({ template: ` <div> <h2>注册内容一</h2> </div> ` })
const cpnC2 = Vue.extend({ template: ` <div> <h2>注册内容二</h2> <cpn1></cpn1> </div> `, components: { cpn1: cpnC1 } })
在组件二中注册子组件一
const app = new Vue({ el: '#app', data: { }, components: { cpn2: cpnC2 } })
在 Vue 实例对象中注册父组件cpn2,显示效果如下
P56 注册组件的语法糖写法
Vue.components ('cpn1',{ template: ` <div> <h2>注册内容</h2> <cpn1></cpn1> </div> ` })
全局组件注册的语法糖
const app = new Vue({ el: '#app', data: { }, components: { 'cpn2': { template: ` <div> <h2>注册内容</h2> <cpn1></cpn1> </div> ` } } })
局部组件的语法糖
P57组件模板的抽离写法
Vue.component('cpn',{ template: '#cpn' })
1.使用 script 注册
<script type="text/x-template" id="cpn"> <div> <h2>组件注册</h2> </div> </script>
2.使用 template 注册
<template id="cpn"> <div> <h2>template 组件注册</h2> </div> </template>
P58 组件的数据存放_为什么要使用函数返回值
获取 title 注册值:
<template id="cpn"> <div> <h2>{{title}}</h2> <h2>template 组件注册</h2> </div> </template>
注册组件并尝试获得 title 属性
const app = new Vue({ el: '#app', data: { title: '标题' }, })
不能在实例化 Vue 对象中注册
Vue.component('cpn',{ template: '#cpn', data() { return { title: '标题_component' } } })
而应在注册构造器中返回注册值
为什么使用函数返回:
将一个计数器封装为组件,测试值
Vue.component('cpn',{ template: '#cpn', data() { // 三个组件的 data 不是一个 data 对象,函数每次使用都会重新创建 return{ counter: 0 } }, methods: { increment() { this.counter++ }, decrement() { this.counter-- } }, })
创建组件并在 data 中 return 值,使用函数返回值每次都会新建函数,避免组件之间影响:
// 使其相互影响的 const obj = { counter: 0 }
当返回是同一个对象时,组件相互影响:
Vue.component('cpn',{ template: '#cpn', data() { // 使用函数每次都返回一个新的对象,就没有相互影响 return obj//影响 }, methods: { increment() { this.counter++ }, decrement() { this.counter-- } }, })
函数返回值的方式可以避免因返回相同对象二影响值的情况
P59 父子组件的通信
父组件向子组件传值的方式 Props:
父组件展示:
<div id="app"> <cpn :cmovies="moveies" :cmessage="message"></cpn> <!-- v-bind 数据绑定 强化写法就写个 : 没有绑定 v-bind 则视作字符. --> </div>
注册子组件:
<template id="cpn"> <div> <h2>{{cmessage}}</h2> <ul> <li v-for="item in cmoveies">{{item}}</li> </ul> </div> </template>
注册父组件(Vue实例化组件同等与组件性质)
const app = new Vue({ el: '#app', data: { message: '你好啊', moveies: ['山贼王', '水影忍者', '金魂'] }, components: { cpn,//增强写法 == cpn: cpn } })
将父组件的 message 和 moveies 传递给子组件
1.数组传递
const cpn = { template: '#cpn', props: ['cmoveies', 'cmessage'],//数组方式 }
2.对象传递: 默认值 default 以及必传值 required
const cpn = { template: '#cpn', props: { // 类型限制: // cmovies: Array, // cmessage: String, //对象写法: //对象写法 cmessage: { type: String, default: '默认值', required: true,//必传,不传会报错 }, //类型是对象Array或数组时,默认值必须是一个函数 cmovies: { type: Array, default() { return [] } }
自定义类型限制示例:
// 自定义类型 // fuction Person (firstName,lastName){ // this.firstName = firstName // this.lastName = lastName // }
P61 子组件向父组件传值的方式 Emit:
//父组件
<div id="app">
<cpn @itemclick="cpClick"></cpn>
</div>
//子组件
<template id="cpn">
<div>
<button v-for="item in categories"
@click="btnClick(item)">
{{item.name}}
</button>
</div>
</template>
const app = new Vue({ el: '#app', data: { }, components:{ cpn }, methods: { cpnClick(item) { console.log('cpnClick',item); } } })
注册父组件
const cpn = { template: '#cpn', data() { return { categories: [ {id:'a',name:'内容a'}, {id:'b',name:'内容b'}, {id:'c',name:'内容c'}, {id:'d',name:'内容d'}, ] } }, methods: { btnClick(item) { this.$emit('itemclick', item); } }, }
注册子组件:
自定义事件,$emit 发送一个事件,
父组件将方法的引用传递给子组件,其中,
cpnClick
是父组件中methods
中定义的方法名称,itemclick
是子组件调用传递过来方法时候的方法名称。<cpn @itemclick="cpnClick"></cpn>//@itemclick == v-on:itemclick ``