组件
大约 6 分钟
组件
组件就是对视图的封装,方便重复使用
模块是对功能逻辑的封装
方式一
Vue.extend结合Vue.component创建
//利用Vue.extend()创建一个组件模板对象
var login = Vue.extend({ template: '<div>登录</div>' })
//使用Vue.component()注册组件
Vue.component('myLogin', login)
<my-login></my-login>
方式二
Vue.component创建
Vue.component('myRegister', { template: '<div>注册</div>' })
<my-register></my-register>
方式三
component结合template方式创建
Vue.component('account', { template: '#account' })
<template id="account">
template需要写在#app之外
<div>帐号</div>
</template>
<account></account>
- 模板
template中只能有一个根节点,组件的名字采用驼峰命名法就需要加上'-', Vue.extend()函数返回一个组件构造器,参数里面是配置项Vue.component('indexA',{..})注册组件,参数1组件名,参数2配置对象
组件中data必须是function,必须返回一个对象
父子组件
<template id="question">
<div>
<h3>Question {{ num | fmtNum }} : ... ? Winner is {{ rightOne }}</h3>
<button @click="num++">Next</button>
<son1 @checks="getAns" :qnum="num"></son1>
<son2 @checks="getAns" :qnum="num"></son2>
</div>
</template>
<div id="app">
<father></father>
</div>
<script>
// var eventBus=new Vue();
Vue.component('father', {
template: '#question',
data() {
return {
num: 1,
rightAns: 'A',
rightOne: '???',
}
},
filters: {
fmtNum(num) {
return num < 10 ? '0' + num : num
},
},
methods: {
getAns(data) {
console.log(data, 111)
this.rightOne = data === 'A' ? 'U !' : '..,Ah-ha,not U'
},
},
components: {
son1: {
props: ['qnum'],
template: "<div>Jim's answer is {{answer}}<button @click='sendAns'>check</button> next {{qnum+1}}</div>",
data() {
return {
answer: 'A',
check: 'right',
}
},
methods: {
sendAns() {
this.$emit('checks', this.answer) //eventBus.$emit(..)
},
},
},
son2: {
props: ['qnum'],
template: "<div>Pi's answer is {{answer}}<button @click='sendAns'>check</button> next {{qnum+1}}</div>",
data() {
return {
answer: 'B',
check: 'wrong',
}
},
methods: {
sendAns() {
this.$emit('checks', this.answer) //eventBus.$emit(..)
},
},
},
},
})
new Vue({
el: '#app',
})
</script>
在父组件模版中给子组件绑定自定义事件
发布者->订阅者
订阅者需要注册一个和发布者发布的消息相同的事件
父向子传值
- 父组件中定义好需要传递给子组件的数据
- 在父组件中使用子组件时,通过属性绑定的方式将定义好的数据传递过去,对于绑定的属性名不做任何要求
- 在子组件内部定义一个
props的属性,这个属性通常是一个数组,数组中的字符串就是用来就收父组件传递过来的值 这个变量必须和父组件中使用子组件时绑定的属性同名
子向父传值
发布->订阅者模式
- 在子组件中定义好需要传递给父组件的数据
- 子组件内部根据业务需求触发
this.$emit('自定义的事件名称','需要发送给父组件的数据this.info') - 在父组件中使用子组件时绑定一个事件,事件名称和消息名称同名,同时事件处理函数要在父组件中定义好,子组件传过来的值就在事件处理函数的参数中
非父子组件传值需要借助一个中介,本质就是一个空的vue实例var bus = new Vue();eventbus事件总线,使用一个公共的Vue实例作为中介,这个中介只负责数据的传输,不会挂载新的数据,需要传递数据的组件调用bus.$emit('消息名称','需要发布的数据')。需要接受数据的组件调用bus.$on('事件名称','事件处理函数'),事件名称和消息名称同名
<div id="app">
<father></father>
</div>
<script>
// 创建一个空的vue实例,作为事件总线
var eventbus = new Vue()
Vue.component('father', {
template: `
<div>
<son></son>
<daughter></daughter>
</div>
`,
components: {
son: {
data() {
return {
mySisterName: '???',
}
},
template: '<span>我妹妹告诉我她叫{{mySisterName}}</span>',
mounted() {
// 通过eventbus的$on()方法去监听兄弟节点发射过来的事件
// $on有两个参数,一个是事件名称,一个是函数,该函数的默认值就是传递过来的数据
eventbus.$on('tellBroMyName', (data) => {
this.mySisterName = data
})
},
},
daughter: {
data() {
return {
myName: '兰兰',
}
},
template: '<button @click="emitMyName">点击就告诉哥哥我叫{{myName}}</button>',
methods: {
emitMyName() {
// 通过事件总线发射一个事件名称和需要传递的数据
eventbus.$emit('tellBroMyName', this.myName)
},
},
},
},
})
var vm = new Vue({
el: '#app',
data: {},
})
</script>
动态组件
<div id="app">
<ul>
<li><a href="javascript:;" @click="currentCom='index'">首页</a></li>
<li><a href="javascript:;" @click="currentCom='productType'">蔬菜</a></li>
<li><a href="javascript:;" @click="currentCom='productType'">水果</a></li>
<li><a href="javascript:;" @click="currentCom='productType'">肉类</a></li>
</ul>
<component :is="currentCom"></component>
</div>
<script>
Vue.component('index', {
template: '<div>首页</div>',
})
Vue.component('productType', {
template: '<div>这里显示商品编号</div>',
})
new Vue({
el: '#app',
data: {
currentCom: '',
},
})
</script>
is属性和component实现组件切换,is指向哪个组件名则component就会被渲染成哪个组件
局部过滤器
不通过Vue.filter('xx',function(){..;return..})全局过滤器来创建,而是通过组件的filters:{ xx(a){..;return..} }创建局部的过滤器
组件生命周期
组件也是一个Vue实例,Vue实例其实就是一个组件,通常称作根组件 Vue实例会存在 初始化-运行中-销毁等多个阶段 这些阶段统称为Vue实例的生命周期,每一个阶段会对应的有一批钩子函数
| 初始化阶段 | |
| beforeCreate | 当 vue 实例一被创建就会执行,此时 vue 中的 data 和 methods 这些属性都还不存在 |
| created | 当 vue 实例创建完毕后 data 中的数据和 methods 中的方法都挂载完毕后执行。数据的赋值和 ajax 请求通常都在 created 函数中执行 |
| beforeMount | 当 DOM 挂载到页面时会自动执行,此时指令还没有被 vue 解析 |
| mounted | 当 DOM 挂载到页面时会自动执行,所有指令都被 vue 解析。如果需要操作真实 DOM 则在 mounted 函数中进行 |
| 运行中阶段 | |
| beforeUpdate | 当 data 中的数据发生变化时会自动执行,只是 data 中的数据发生了变化但还没有重新更新到 DOM 中 |
| updated | 当 data 中的数据发生变化时会自动执行,data 中的数据和视图中显示的数据都已经完全被修改了 |
| 销毁阶段 | |
| beforeDestroy | vue 实例被销毁之前,当执行这个函数时 data 中的数据和 methods 中的方法还可以使用 |
| destroyed | vue 实例完全被销毁,当执行这个函数时 data 中的数据和 methods 中的方法都不可以使用了 |
构造函数:使用 new 关键字引导执行的函数叫做构造函数 回调函数:当一个函数作为参数进行传递时,这个函数称作回调函数 钩子函数:系统提前定义好的函数,会在适当的时机自动执行
