目录
一、注册组件的基本步骤
-
创建组件构造器
-
注册组件
-
使用组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<my-cpn></my-cpn>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
// 1、创建组件构造对象
const cpnC = Vue.extend({
template: `
<div>
<h2>标题</h2>
<p>内容1</p>
<p>内容2</p>
</div> `
})
// 2、注册组件
Vue.component('my-cpn', cpnC) //(组件的标签名,组件构造对象)
const app = new Vue({
el: "#app",
data: {
number: 10
},
methods: {
}
})
</script>
</body>
</html>
二、全局组件与局部组件
全局组件:可以在多个Vue的实例下使用
局部组件 :只能在当前Vue实例下使用
- 全局组件:在Vue实例外注册
- 局部组件:在Vue实例里注册
<script>
// 1、创建组件构造对象
const cpnC = Vue.extend({
template: `
<div>
<h2>标题</h2>
<p>内容1</p>
<p>内容2</p>
</div> `
})
// 2、注册组件(全局组件)
Vue.component('my-cpn', cpnC) //(组件的标签名,组件构造对象)
const app = new Vue({
el: "#app",
data: {
number: 10
},
// 2、注册组件(局部组件)
components: {
cpn: cpnC // cpn使用组件时的标签名:构造器
}
})
</script>
三、父组件与子组件
1、定义
子组件:在父组件的构造对象中注册的组件为该组件的子组件
2、通信
- 通过props向子组件传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn v-bind:cnumber="number" :cmovies="movies"></cpn>
</div>
<template id="cpn">
<div>
<p>{{cnumber}}</p>
<h2>{{cmovies}}</h2>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
const cpn = {
template: `#cpn`,
// 1、数组类型
props: ['cnumber', 'cmovies'],
// 2、对象类型(可以设置变量类型)
props: {
cnumber: Number,
cmovies: Array
}
}
const app = new Vue({
el: "#app",
data: {
number: 10,
movies: ["星际穿越", "阿凡达", "大话西游", "实间管理局"]
},
components: {
cpn
}
})
</script>
</body>
</html>
- 通过事件向父组件发送信息
<!--父子通信,子向父-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn @itemclick="cpnClick"></cpn>
<h2>{{id}}</h2>
</div>
<template id="cpn">
<div>
<button
v-for="item in categories"
@click="btnClick(item)">
{{item.name}}
</button>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
// 子组件
const cpn = {
template: `#cpn`,
data() {
return {
categories: [
{id: 'aaa', name: '热门推荐'},
{id: 'bbb', name: '手机数码'},
{id: 'ccc', name: '家用家电'},
{id: 'ddd', name: '电脑办公'}
]
}
},
methods: {
btnClick(item) {
this.$emit('itemclick', item)
}
}
}
// 父组件
const app = new Vue({
el: "#app",
data: {
id: '0'
},
methods: {
cpnClick(item) {
this.id = item.id
}
},
components: {
cpn
}
})
</script>
</body>
</html>
四、组件的语法糖
使用构造方法直接代替注册时的构造对象
Vue.component('my-cpn', {
template: `
<div>
<h2>标题</h2>
<p>内容1</p>
<p>内容2</p>
</div> `
}) //(组件的标签名,组件构造对象)
五、组件模板抽离
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<!--1、script标签,注意:类型必须是text/x-template类型-->
<script type="text/x-template" id="cpn">
<div>
<h2>标题</h2>
<p>段落1</p>
<p>段落2</p>
</div>
</script>
<!--2、template标签-->
<template id="cpn">
<div>
<h2>标题</h2>
<p>段落1</p>
<p>段落2</p>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
Vue.component('cpn', {
template: `#cpn`
})
const app = new Vue({
el: "#app",
data: {
number: 10
},
methods: {
}
})
</script>
</body>
</html>
六、组件数据存储
在组件声明注册中使用
data() {
return {
title:'标题'
}
}来为组件中的元素赋值
七、自制计数器组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<counter></counter>
</div>
<template id="counter">
<div>
<button @click="numSub">-</button>
<span>{{number}}</span>
<button @click="numAdd">+</button>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
Vue.component('counter', {
template: `#counter`,
data() {
return {
number: 0
}
},
methods: {
numSub() {
if (this.number > 0) {
this.number--
}
},
numAdd() {
this.number++
}
}
})
const app = new Vue({
el: "#app",
data: {
}
})
</script>
</body>
</html>
八、插槽(slot)
组件的插槽
组件的插槽是为了让我们封装的组件更加具有扩展性
让使用者可以决定组件内部的一些内容到底展示什么
1、为什么要使用插槽
类似下图中的导航栏,它们存在一定的共性,因此为了提高复用度,减少开发成本,应将其封装成一个组件;但是这些导航栏又有很多不同之处,例如后三个都有返回键,而第一个没有。因此就需要使用插槽来解决这一问题:完全相同部分封装进组件,不同的地方暴露为插槽。(抽取共性,保留不同)
2、插槽的使用
- 将自定义的组件插入到插槽中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn><button>+</button></cpn>
<cpn>0</cpn>
<cpn><button>-</button></cpn>
<cpn>总计</cpn>
</div>
<template id="cpn">
<div>
<h2>我是组件</h2>
<p>我是组件,哈哈哈</p>
<slot></slot>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
const cpn = {
template: `#cpn`
}
const app = new Vue({
el: "#app",
data: {
number: 10
},
components: {
cpn
}
})
</script>
</body>
</html>
- 插槽也可以设置默认内容(例如京东例子,可以将导航栏左部默认设置为返回btn)
<slot><button>按钮</button></slot>
- 当有多个插槽时需要为插槽设置名字
<div id="app">
<cpn><span slot="up">上</span></cpn>
<cpn></cpn>
<cpn></cpn>
<cpn><span slot="down">下</span></cpn>
</div>
<template id="cpn">
<div>
<h2>我是组件</h2>
<p>我是组件,哈哈哈</p>
<slot name="up"><button>按钮</button></slot>
<slot name="down"></slot>
</div>
</template>
- 作用域插槽
<div id="app">
<cpn>
<template slot-scope="slot">
<span v-for="item in slot.data">{{item}}-</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="someMovies">
<ul>
<li v-for="item in someMovies">{{item}}</li>
</ul>
</slot>
</div>
</template>
components: {
cpn: {
template: `#cpn`,
data() {
return {
someMovies: ["星际穿越", "阿凡达", "大话西游", "实间管理局"]
}
}
}
}