组件就是一个小型的Vue实例,它里面除了不能设置el选项,其他选项它都有。组件的名称不要跟
原生html元素重名,一般用短横线分隔命名,例如 my-component
组件有两种注册方法:1.全局注册 2.局部注册
全局注册: 通过Vue.component() 来创建组件: 定义全局组件,让每一个Vue实例都可以使用
Vue.component('my-component', {
// ... 选项 ...
})
局部注册 :在vue实例中通过components选项创建组件,只能在当前实例使用
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
props选项用来用于定义组件标签上属性,它的值可以是一个字符串数组,里面定义每一个标
签属性名称,这是简单用法,不能对属性做严格的验证。props的值也可以是一个对象,里面定义
的每个标签属性名称也可以是一个对象,在这个对象里面定义该属性的完整信息。一般来说父组件
给子组件传值通过props,而子组件可以通过触发自定义事件的方式给父组件传值。这样一来就实现
了父子组件的通信。
// 组件的模板
template:
`<div class='box'>
<h4 class='id'>{{id}}</h4>
<p class='name'>{{name}}</p>
<p class='price'>{{price}}</p>
</div>`,
//定义组件标签上的属性
props: {
id: {
// 数据类型
type: String,
//require:true时,数据不能为空
require: true,
//默认值
default: ''
},
name: {
type: String,
require: true,
default: ''
},
price: {
type: String,
require: true,
default: ''
}
},
//组件自己的数据
data() {
return {
name: '我是组件'
}
},
注意:Vue实例的data选项可以是一个对象,也可以是一个方法,由该方法返回一个对象。
但是在组件中,data选项必须是一个方法,由该方法返回一个对象。因为组件可能会使用很多次,
如果data选项是对象的话,会导致多个组件使用了同一份数据,从而导致混乱。
① 自定义组件
1.counter组件
<div id="app">
衣服:{{clothesNum}}<a-counter :count="clothesNum" :min-count='2' :max-count='25' @sync-count='syncClothes'>
</a-counter>
鞋子:{{shoesNum}}<a-counter :count="shoesNum" :min-count='4' :max-count='30' @sync-count='syncShoes'></a-counter>
裤子:{{pantsNum}}<a-counter :count="pantsNum" :min-count='5' :max-count='15' @sync-count='syncPants'></a-counter>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
Vue.component('a-counter', {
// template选项,用于定义组件的模板
template:
`<div class="counter">
<button @click='sub' :disabled='myCount==minCount'>-</button>
<input type="text" readonly :value='myCount'>
<button @click='add' :disabled='myCount==maxCount'>+</button>
</div>`,
props: {
// 数量
count: {
// 数据类型
type: Number,
//require:true时,数据不能为空
require: true,
//默认值
default: 5
},
minCount: {
type: Number,
default: 1
},
maxCount: {
type: Number,
default: 20
}
},
// // 定义组件的数据
data() {
return {
// 从props里面将count的值给myCount复制一份
myCount: this.count
}
},
methods: {
//数量减方法
add() {
this.myCount++
},
// 数量加方法
sub() {
this.myCount--
},
},
watch: {
// 侦听myCount是否发生变化
myCount() {
// 触发自定义事件,注意:事件名称中不能采用大写字母
this.$emit("sync-count", this.myCount)
}
},
})
new Vue({
el: "#app",
data() {
return {
// 衣服的数量
clothesNum: 3,
// 裤子的数量
shoesNum: 5,
// 鞋子的数量
pantsNum: 6
}
},
methods: {
// 同步衣服的数量
syncClothes(e) {
this.clothesNum = e
},
// 同步裤子的数量
syncShoes(e) {
this.shoesNum = e
},
// 同步鞋子的数量
syncPants(e) {
this.pantsNum = e
},
},
// 局部注册组件
components: {
}
})
</script>
2.评分组件
<div id="app">
质量:{{quality}}<a-star :score='quality' @syncscore='syncquality'></a-star>
物流:{{logistics}}<a-star :score='logistics' @syncscore='synclogistics'></a-star>
</div>
<div id="app2">
外观:{{exterior}}<a-star :score='exterior' @syncscore='syncexterior'></a-star>
客服:{{service}}<a-star :score='service' @syncscore='syncservice'></a-star>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
Vue.component('a-star', {
template:
`<div class="star">
<i :class="index<myScore?'icon-shixinxingxing':'icon-xingxing' " class="iconfont"
v-for='(item,index) in 10' :key='index' @mouseenter="mouseenter(index)" @mouseleave='mouseleave' @click='click(index)'></i>
</div>`,
//定义组件的标签属性
props: ['score'],
data() {
return {
// 将组件接收到的值,在组件内部中转一下
myScore: this.score,
// 备份一下score值
backMyScore: this.score
}
},
methods: {
// 鼠标进入时,调用的方法
mouseenter(index) {
this.myScore = index + 1
},
//鼠标离开时,调用的方法
mouseleave() {
this.myScore = this.backMyScore
},
//鼠标点击时,调用的方法
click(index) {
this.backMyScore = index + 1
}
},
watch: {
// 触发自定义事件
myScore() {
this.$emit('syncscore', this.myScore)
}
},
})
new Vue({
el: '#app',
data() {
return {
//质量
quality: 2,
//物流
logistics: 4,
}
},
// 方法
methods: {
// 同步质量评分
syncquality(e) {
this.quality = e
},
// 同步物流评分
synclogistics(e) {
this.logistics = e
},
},
})
new Vue({
el: '#app2',
data() {
return {
//外观
exterior: 5,
//客服
service: 3,
}
},
methods: {
// 同步外观评分
syncexterior(e) {
this.exterior = e
},
// 同步客服评分
syncservice(e) {
this.service = e
},
},
})
</script>
② 组件中插槽的用法
slot标签 用于在组件的内部定义插槽,组件标签之间的内容,会在插槽所在位置呈现
<div id="app">
<b-box title="iphone11" class="box">
<input type="text">
<button>购买</button>
</b-box>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
},
// 定义组件
components: {
'b-box': {
// 组件的模板
template:
`<div class="box">
<div class="title">{{title}}</div>
<div class="content">
<slot></slot>
</div>
</div>`,
// 定义组件标签上的属性
props: ["title", "content"],
}
}
})
</script>
具名插槽:
在组件内部通过slot标签定义插槽,在通过name属性给插槽定义名字,这样的插槽称之为:具名插
槽。插槽的默认名称是:default。如果有多个插槽,允许其中一个插槽不定义名称
<div id="app">
<b-box>
<!-- template标签指定它里面的内容在哪一个具体的插槽中呈现 -->
<template v-slot:header>
<h4>好好学习</h4>
<h4>天天向上</h4>
</template>
<template v-slot:default>
<h4>你好</h4>
<h4>世界</h4>
</template>
<!-- v-slot:的简写是# -->
<template #footer>
<a href="http://www.baidu.com">百度</a>
<a href="http://www.taobao.com">淘宝</a>
</template>
</b-box>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
Vue.component('b-box', {
template:
`<div class="box">
<h2>我是组件</h2>
<div class="header">
<slot name="header"></slot>
</div>
<div class="main">
<slot></slot>
</div>
<div class="footer">
<slot name="footer"></slot>
</div>
</div>`
})
new Vue({
el: '#app',
})
</script>
作用域插槽:
可以在slot标签上绑定属性,这样外面在使用该插槽时,就可以获取到上面绑定的数据。这样的插
槽,我们称之为:作用域插槽。
<div id="app">
<b-box>
<!-- 注意:一定要用使用具名插槽的方式去接收作用域插槽传递回来的数据,
通常我们会定义scope变量,就收传回来的数据。 -->
<!-- 此props变量是用来接收所有的插槽的属性的对象=>props可以任意取名-->
<template v-slot:exit="props">
<button @click="props.item.name='苹果'">修改</button>
<button @click="props.list.splice(props.index,1)">删除</button>
</template>
</b-box>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
Vue.component('b-box', {
template:
`<div class="box">
<ul>
<li v-for="(item,index) in list" :key="index">{{item.id}}--{{item.name}}
<slot name="exit" v-bind:item="item" v-bind:list="list" v-bind:index="index"></slot>
</li>
</ul>
</div>`,
data() {
return {
list: [
{
id: 1001,
name: '薯片'
},
{
id: 1002,
name: '饼干'
},
{
id: 1003,
name: '面包'
},
{
id: 1004,
name: '糖果'
},
]
}
},
})
new Vue({
el: '#app',
})
</script>
③父子组件
一般是先创建父组件再创建子组件,先渲染子组件再渲染父组件。在父组件创建完成到挂载完成之
间,包含完整的子组件的生命周期。注意:定义插槽后才能嵌套子组件。在子组件中可以通过
$parent获取父组件的实例,$root获取根组件实例,而父组件通过$children获取的是所有子组件的
实例。但是页面的结构出现了调整,这里获取的具体的组件可以就对不上号了,所以给组件标签
添加一个ref属性,然后就可以通过$refs返回拥有ref属性的组件,在$refs对象中,保存着所有添加
了ref属性的组件实例。
<div id="app">
<div class="box">
<h4>app</h4>
<h4>姓名:{{name}}</h4>
<h4>年龄:{{age}}</h4>
<button @click="updateCar">修改b-one的汽车</button>
<button @click="updatePlane">修改b-two的飞机</button>
</div>
<b-one ref="one">
<b-three></b-three>
</b-one>
<b-two ref="two"></b-two>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
// 定义b-one组件
Vue.component('b-one', {
template:
`<div class="one">
<h4>b-one--------{{car.name}}-------{{car.price}}</h4>
<h4>App----姓名:{{myname}},年龄:{{myage}}</h4>
<slot></slot>
</div> `,
data() {
return {
car: {
name: '奔驰',
price: '50W'
}
}
},
computed: {
myname() {
return this.$parent.name
},
myage() {
return this.$parent.age
}
},
created() {
console.log('b-one----created');
},
mounted() {
console.log('b-one----mounted');
},
})
// 定义b-two组件
Vue.component('b-two', {
template:
`<div class="two">
<h4>b-two------{{plane.name}}-------{{plane.price}}</h4>
</div> `,
data() {
return {
plane: {
name: '波音747',
price: '20亿'
}
}
},
})
// 定义b-three组件
Vue.component('b-three', {
template:
` <div class="three">
<h4>b-three---App----姓名:{{name}}----年龄:{{age}}</h4>
</div>`,
computed: {
name() {
// 通过$parent还可以继续获取它的父级组件
return this.$parent.$parent.name
},
age() {
// $root获取根组件
return this.$root.age
}
},
created() {
console.log('b-three----created');
},
mounted() {
console.log('b-three----mounted');
},
})
// 创建vue实例
new Vue({
el: '#app',
created() {
console.log('app----created');
},
mounted() {
console.log('app----mounted');
// 根据组件在页面中的顺序返回所有的组件
console.log(this.$children);
// 返回所有带有ref属性的组件
console.log(this.$refs);
},
data() {
return {
name: '张三',
age: 20
}
},
methods: {
//修改汽车的方法
updateCar() {
/* this.$children[0].car = {
name:'宝马',
price:'40W'
} */
this.$refs.one.car = {
name: '宝马',
price: '40W'
}
},
// 修改飞机的方法
updatePlane() {
/* this.$children[1].plane = {
name:'长征2号',
price:'30亿'
} */
this.$refs.two.plane = {
name: '长征2号',
price: '30亿'
}
}
},
})
</script>
1.自定义表格组件--仿iview
<div id="app">
<b-table :data="data1" :columns="columns1"></b-table>
<hr>
<b-table :data="data2" :columns="columns2"></b-table>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
// 定义一个b-table组件
Vue.component('b-table', {
template:
`<table>
<tr>
<th v-for="(item,index) in columns" :key="index">{{item.title}}</th>
</tr>
<tr v-for="(item,index) in data" :key="index">
<td v-for="(item2,index2) in columns" :key="index2">{{item[item2.key]}}</td>
</tr>
</table>`,
// 定义组件标签上的属性,用于接收外部传给组件的数据
props: ['data', 'columns'],
})
// 创建vue实例
new Vue({
el: '#app',
data() {
return {
// 表格的列数据
columns1: [
{
title: '姓名',
key: 'name'
},
{
title: '年龄',
key: 'age'
},
{
title: '性别',
key: 'sex'
},
{
title: '工资',
key: 'money'
}
],
// 表格数据
data1: [{
name: '张三',
age: 20,
sex: '男',
money: 10000
}, {
name: '李四',
age: 22,
sex: '女',
money: 20000
}, {
name: '王五',
age: 24,
sex: '女',
money: 30000
}],
columns2: [
{
title: '编号',
key: 'id'
},
{
title: '车名',
key: 'name'
},
{
title: '产地',
key: 'address'
},
],
// 表格数据2
data2: [{
id: '1001',
name: '奔驰',
address: '德国'
}, {
id: '1002',
name: '红旗',
address: '中国'
}, {
id: '1003',
name: '捷豹',
address: '英国'
}]
}
},
})
</script>
2.自定义表格组件--仿element-ui
<div id="app">
<b-table :data="data1">
<b-table-column prop="name" label="姓名"></b-table-column>
<b-table-column prop="age" label="年龄"></b-table-column>
<b-table-column prop="sex" label="性别"></b-table-column>
<b-table-column prop="money" label="工资"></b-table-column>
</b-table>
<hr>
<b-table :data="data2">
<b-table-column prop="id" label="编号"></b-table-column>
<b-table-column prop="name" label="车名"></b-table-column>
<b-table-column prop="address" label="产地"></b-table-column>
</b-table>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
// 定义一个b-table-column组件
Vue.component('b-table-column', {
template: `<th>{{label}}</th>`,
props: ['prop', 'label'],
mounted() {
// 子组件挂载完成时,将获取到的属性的名称,添加到父组件的columns数组中。
this.$parent.columns.push(this.prop)
},
})
// 定义一个b-table组件
Vue.component('b-table', {
template:
`<table>
<tr>
<slot></slot>
</tr>
<tr v-for="(item,index) in data" :key="index">
<td v-for="(item2,index2) in columns" :key="index2">{{item[item2]}}</td>
</tr>
</table>`,
// 定义组件标签上的属性,用于接收外部传给组件的数据
props: ['data'],
data() {
return {
// 该数组存放属性的名称
columns: []
}
},
})
// 创建vue实例
new Vue({
el: '#app',
data() {
return {
// 表格数据
data1: [{
name: '张三',
age: 20,
sex: '男',
money: 10000
}, {
name: '李四',
age: 22,
sex: '女',
money: 20000
}, {
name: '王五',
age: 24,
sex: '女',
money: 30000
}],
// 表格数据2
data2: [{
id: '1001',
name: '奔驰',
address: '德国'
}, {
id: '1002',
name: '红旗',
address: '中国'
}, {
id: '1003',
name: '捷豹',
address: '英国'
}]
}
},
})
</script>
④ 混入基础
1.混入提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任
意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
// 1.创建构造器
var Profile = Vue.extend({
template: '<p>1.{{name}}---{{age}}---{{sex}}</p>',
data: function () {
return {
name: '张三',
age: 26,
sex: '男'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#app1')
//2.定义一个混入对象
let myMixin = {
data() {
return {
name: "混入-----mixin"
}
},
}
//定义一个使用混入对象的组件
let component = Vue.extend({
mixins: [myMixin]
})
new component().$mount('#app2')
2.当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。比如,数据对象在内
部会进行递归合并,并在发生冲突时以组件数据优先。
let mixin = {
data() {
return {
name: '张三',
age: 25,
sex: '男',
address: '上海',
phone: 18546797959,
email: '1659562326@qq.com'
}
},
}
new Vue({
el: '#app3',
mixins: [mixin],
data() {
return {
name: '李四',
age: 28,
sex: '女',
}
},
methods: {
fun1() {
console.log(this.$data);
// {name: '李四',age: 28, sex: '女',
address: '上海',
phone: 18546797959,
email: '1659562326@qq.com'}
}
},
})
3.同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之
前调用。
let mixin2 = {
data() {
return {
content1: '混入对象的钩子被调用'
}
},
created() {
console.log(this.content1);
},
}
new Vue({
el: '#app4',
mixins: [mixin2],
data() {
return {
content2: '组件钩子被调用'
}
},
created() {
console.log(this.content2);
},
})
// => "混入对象的钩子被调用"
// => "组件钩子被调用"
4.值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对
象键名冲突时,以组件对象优先。
let mixin3 = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var vm = new Vue({
mixins: [mixin3],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
5.全局混入,混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之
后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
Vue.mixin({
created: function () {
let myOption = this.$data.myOption
if (myOption) {
console.log(myOption)
}
}
})
new Vue({
data() {
return {
myOption: 'hello!'
}
},
})
// => "hello!"
6. 混入ajax
<div id="app1">
<template>
<el-table :data="students" style="width: 100%" height="250">
<el-table-column fixed prop="StudentNo" label="学号" width="150">
</el-table-column>
<el-table-column prop="StudentName" label="姓名" width="120">
</el-table-column>
<el-table-column prop="Grade.GradeName" label="年级" width="120">
</el-table-column>
<el-table-column prop="Phone" label="电话" width="120">
</el-table-column>
<el-table-column prop="Address" label="地址" width="300">
</el-table-column>
<el-table-column prop="Email" label="邮箱" width="120">
</el-table-column>
</el-table>
</template>
</div>
<hr>
<div id="app2">
<template>
<el-table :data="subjects" style="width: 100%" height="250">
<el-table-column fixed prop="SubjectName" label="课程名称" width="150">
</el-table-column>
<el-table-column prop="Grade.GradeName" label="课程年级" width="120">
</el-table-column>
<el-table-column prop="ClassHour" label="课程课时" width="120">
</el-table-column>
</el-table>
</template>
<hr>
<p>课程名称:<input type="text" v-model="subject.subjectName"></p>
<p>课程年级:<select v-model='subject.gradeId'>
<option value="0">S1</option>
<option value="1">S2</option>
<option value="2">Y2</option>
</select></p>
<p>课程课时:<input type="text" v-model="subject.classHour"></p>
<p><button @click="add">添加</button></p>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.js"></script>
<script>
// 将ajax请求相关的操作,通过mixin混入给Vue
Vue.mixin({
data() {
return {
// 接口根路径
base_url: 'https://bingjs.com:8001'
}
},
methods: {
// get方法
async $get(url, params) {
let { data } = await axios.get(this.base_url + url, { params })
return data
},
// post方法
async $post(url, params) {
let { data } = await axios.post(this.base_url + url, params)
return data
}
},
})
new Vue({
el: '#app1',
data() {
return {
// 学生信息数组
students: []
}
},
created() {
this.getStudents()
},
methods: {
async getStudents() {
let students = await this.$get('/Student/GetAll')
this.students = students
}
},
})
new Vue({
el: '#app2',
data() {
return {
// 课程信息
subjects: [],
subject: {
subjectName: '',
classHour: '',
gradeId: '0'
}
}
},
created() {
this.getSubjects()
},
methods: {
async getSubjects() {
let subjects = await this.$get('/Subject/GetAll')
this.subjects = subjects
},
async add() {
let r = await this.$post('/Subject/Add', this.subject)
if (r) {
alert('添加成功!')
this.getSubjects()
}
}
},
})
</script>
⑤ 深入理解v-model和sync修饰符
v-model指令是对v-bind:value 和 v-on:input的简写。将自定义组件,绑定数据的属性改成value,
监听事件的名称改成input,也可以使用v-model简写形式。
<div id="app">
<div>
姓名:{{name}}<input type="text" v-bind:value="name" v-on:input="name=$event.target.value">
</div>
<div>
姓名:{{name}}<input type="text" v-model="name">
</div>
<div>
衣服:{{yfcount}}<b-counter v-bind:value="yfcount" v-on:input="yfcount=$event"></b-counter>
</div>
<div>
衣服:{{yfcount}}<b-counter v-model="yfcount"></b-counter>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
// 定义一个数据加减的组件
Vue.component('b-counter', {
template:
` <div class="counter">
<button @click="jian" :disabled="myCount===minCount">-</button>
<input type="text" :value="myCount" readonly>
<button @click="jia" :disabled="myCount===maxCount">+</button>
</div>`,
props: {
// 数量
value: {
// 类型
type: Number,
// 非空
required: true,
},
// 最小值
minCount: {
type: Number,
// 默认值
default: 1
},
// 最大值
maxCount: {
type: Number,
default: 10
}
},
// 定义组件的数据
data() {
return {
// 从props里面将value的值给myCount复制一份
myCount: this.value
}
},
// 定义组件的方法
methods: {
//数量减方法
jian() {
this.myCount--
},
// 数量加方法
jia() {
this.myCount++
}
},
// 侦听器
watch: {
// 侦听myCount是否发生变化
myCount() {
// 触发自定义事件,注意:事件名称中不能采用大写字母
this.$emit('input', this.myCount)
}
}
})
new Vue({
el: "#app",
data() {
return {
name: '张三',
// 衣服的数量
yfcount: 2
}
},
})
</script>
组件只回传一份数据,用v-model,但是如果组件回传多份数据,则用.sync修饰符,
如果触发的事件名称是update:属性名,那么就可以使用.sync修饰符简化调用的过程。
<div id="app">
<div>
<h4>衣服数量:{{yfcount}}</h4>
<h4>裤子数量:{{kzcount}}</h4>
<h4>鞋子数量:{{xzcount}}</h4>
<!-- <b-box :yfcount="yfcount" :kzcount="kzcount" :xzcount="xzcount"
@update:yfcount="yfcount=$event" @update:kzcount="kzcount=$event"
@update:xzcount="xzcount=$event"></b-box> -->
<b-box :yfcount.sync="yfcount" :kzcount.sync="kzcount" :xzcount.sync="xzcount"></b-box>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
// 定义一个数据加减的组件
Vue.component('b-counter', {
template:
`<div class="counter">
<button @click="del" :disabled="myCount===minCount">-</button>
<input type="text" :value="myCount" readonly>
<button @click="add" :disabled="myCount===maxCount">+</button>
</div>`,
props: {
// 数量
value: {
// 类型
type: Number,
// 非空
required: true,
},
// 最小值
minCount: {
type: Number,
// 默认值
default: 1
},
// 最大值
maxCount: {
type: Number,
default: 10
}
},
// 定义组件的数据
data() {
return {
// 从props里面将value的值给myCount复制一份
myCount: this.value
}
},
// 定义组件的方法
methods: {
//数量减方法
del() {
this.myCount--
},
// 数量加方法
add() {
this.myCount++
}
},
// 侦听器
watch: {
// 侦听myCount是否发生变化
myCount() {
// 触发自定义事件,注意:事件名称中不能采用大写字母
this.$emit('input', this.myCount)
}
}
})
// 定义一个b-box组件
Vue.component('b-box', {
// 模板中必须包含一个根标签
template:
`<div>
<div>衣服:<b-counter v-model="myyfcount"></b-counter></div>
<div>裤子:<b-counter v-model="mykzcount"></b-counter></div>
<div>鞋子:<b-counter v-model="myxzcount"></b-counter></div>
</div>`,
props: ['yfcount', 'kzcount', 'xzcount'],
data() {
return {
// 将props传进来的数据,在data中备份一下,从此以后操作data中的数据
myyfcount: this.yfcount,
mykzcount: this.kzcount,
myxzcount: this.xzcount
}
},
watch: {
myyfcount() {
// 注意:这里触发事件的名称是:update:属性名;
// 如果满足该规则,那么在触发事件时,就可以使用sync修饰符简化调用的过程。
this.$emit('update:yfcount', this.myyfcount)
},
mykzcount() {
this.$emit('update:kzcount', this.mykzcount)
},
myxzcount() {
this.$emit('update:xzcount', this.myxzcount)
}
}
})
new Vue({
el: "#app",
data() {
return {
// 衣服的数量
yfcount: 2,
// 裤子的数量
kzcount: 3,
// 鞋子的数量
xzcount: 5
}
},
})
</script>
⑥ 组件和vue实例生命周期的执行顺序
在vue的整个生命周期中在渲染前到渲染后会把组建的整个生命周期走完
即vue的beforeCreate()=>created()=>beforeMount()=>组件的beforeCreate()=>created()
=>beforeMount()=>mounted()=>vue的mounted()