@TOC
1 注册组件的基本步骤
- 创建爱你组件构造器:
Vue.extends()
- 注册组件:
Vue.component()
- 使用组件
2 组件的基本使用
代码语言:html复制<div id="app">
<!-- 3 使用组件 -->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
// 1 创建组件构造器对象
const cpnConstructor = Vue.extend({
template: `
<div>
<h2>标题</h2>
<p>哈哈哈</p>
</div>
`
})
// 2 注册组件
Vue.component('my-cpn', cpnConstructor)
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排"
}
})
</script>
3 全局组件和局部组件
代码语言:html复制<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实例1
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排"
},
// 局部组件
components:{
// cpn使用组件时的标签名
cpn:cpnC
}
})
// Vue实例2
const app2 = new Vue({
el: '#app2'
})
</script>
4 父组件和子组件
代码语言:html复制<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1 创建爱你第1个组件构造器(子组件)
const cpnC1 = Vue.extend({
template: `
<div>
<h2>标题1</h2>
<p>666</p>
</div>
`
})
// 2 创建爱你第2个组件构造器(父组件)
const cpnC2 = Vue.extend({
template: `
<div>
<h2>标题2</h2>
<p>777</p>
<cpn1></cpn1>
</div>
`,
components: {
cpn1: cpnC1
}
})
// root组件
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排"
},
components: {
cpn2: cpnC2
}
})
</script>
5 注册组件语法糖
主要省区了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替
代码语言:html复制<script>
// 1 全局组件注册的语法糖
// 1 创建组件构造器
// const cpn1 = Vue.extend()
// 2 组件注册(全局方式)
Vue.component('cpn1', {
template: `
<div>
<h2>标题1</h2>
<p>666</p>
</div>
`
})
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排"
},
components: {
'cpn2': {
template: `
<div>
<h2>标题2</h2>
<p>777</p>
</div>
`
}
}
})
</script>
6 组件模板分离写法 组件数据存放
存放
- 组件对象向也有一个data属性(也可以有methods等属性)
- 只是这个data属性必须是一个函数
- 而且这个函数返回一个对象,对象内部保存着数据
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<!-- 1 script标签,注意:类型必须是text/x-template -->
<script type="text/x-template" id="cpn1">
<div>
<h2>标题1</h2>
<p>666</p>
</div>
</script>
<!-- 2 template标签 -->
<template id="cpn2">
<div>
<h2>标题2</h2>
<p>777</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 注册一个全局组件
Vue.component('cpn1', {
template: '#cpn1'
})
Vue.component('cpn2', {
template: '#cpn2'
})
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排"
}
})
</script>
7 组件中data为什么是函数
代码语言:html复制<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<!-- 组件实例对象 -->
<template id="cpn">
<div>
<h2>当前计数:{{ counter }}</h2>
<button @click="increment"> </button>
<button @click="decrement">-</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 1 注册组件
Vue.component('cpn', {
template: '#cpn',
data() {
return {
counter: 0
}
},
methods: {
increment() {
this.counter ;
},
decrement() {
this.counter--;
}
}
})
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排"
}
})
</script>
8 父子组件的通信
- 通过props想自键传递数据
- 通过时间向父组件发送消息
props数据验证
支持:String、Number、Boolean、Array、Object、Date、Function、Symbol
代码语言:html复制<div id="app">
<!-- <cpn v-bind:cmovies="movies" :cmessage="message"></cpn>-->
<cpn v-bind:cmovies="movies"></cpn>
</div>
<template id="cpn">
<div>
<h2>{{ cmessage }}</h2>
<ul>
<li v-for="item in cmovies">{{ item }}</li>
</ul>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子:props
const cpn = {
template: '#cpn',
// props: ['cmovies', 'cmessage'],
props: {
// 1 类型限制
// cmovies:Array,
// cmessage:String
// 2 提供一些默认值
cmessage: {
type: String,
default: '666',
required: true
},
// 类型是对象或者数组时,默认值必须是一个函数
cmoves: {
type: Array,
default() {
return []
}
}
},
data() {
return {}
},
methods: {}
}
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排",
movies: ['三体', '金刚狼', '疯狂外星人']
},
components: {
cpn
}
})
</script>
9 父子通信-父传子(props中的驼峰命名)
代码语言:html复制<div id="app">
<cpn :c-info="info" :child-my-message="message"></cpn>
</div>
<template id="cpn">
<h2>{{ cInfo }}</h2>
</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: "有勇气的牛排",
age: 18,
sex: 0
}
},
components: {
cpn
}
})
</script>
10 组件通信-子传父(自定义事件)
什么时候需要使用自定义事件?
- 当子组件需要想父组件传递数据时,就要用到自定义事件了
- v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件
自定义事件的流程
- 在子组件中,通过$emit()来触发事件。
- 在父组件中,通过v-on来鉴定子组件事件
<!-- 子组件模板 -->
<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 子组件
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id: '1', name: '热门推荐'},
{id: '2', name: '手机数码'},
{id: '3', name: '家电'},
{id: '4', name: '电脑办公'},
{id: '5', name: '衣服'},
{id: '6', name: '玩具'}
]
}
},
methods: {
btnClick(item) {
// console.log(item)
// 发射事件: 自定义事件
this.$emit('item-click', item)
}
}
}
// 2 父组件
const app = new Vue({
el: '#app',
data: {
message: '有勇气的牛排'
},
components: {
cpn
},
methods: {
cpnclick(item) {
console.log('cpnclick', item);
}
}
})
</script>
11 12 组件通信 案例
见gitee源代码
13 父子组件的访问方式:$children
有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是组件访问跟组件。
- 父组件访问子组件:使用$children或者$refs(reference 引用)
- 子组件访问父组件:$parent
<div id="app">
<cpn></cpn>
<cpn ref="key1"></cpn>
<cpn></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: "你好,有勇气的牛排"
},
methods: {
btnClick() {
// 1 $children
// console.log(this.$children);
// this.$children[0].showMessage();
// this.$children[0].name;
// for(let c of this.$children){
// c.showMessage();
// }
// 2 $refs => 对象类型,默认是一个空对象 ref='key1'
console.log(this.$refs.key1.name);
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: '我是子组件的name'
}
},
methods: {
showMessage() {
console.log('showMessage');
}
}
}
}
})
</script>