二、组件化开发
组件使用的三个步骤:
- 创建组件的构造器 Vue.extend()方法创建组件的构造器
- 注册组件 Vue.component()注册组件
- 使用组件在Vue的实力范围内使用组件(el指定的范围内进行使用)
在开发中基本使用的是局部组件很少使用全局组件
2.1 创建局部组件与全局组件
<script src="../js/vue.js"></script>
<div id="app">
<span>{{message}}</span>
<!-- <my-cpn></my-cpn> -->
<!-- 只能够在Vue管理的范围内进行使用 -->
<cpn1></cpn1>
</div>
<div id="app1">
<cpn1></cpn1>
</div>
<!-- <my-cpn></my-cpn> -->
<!--无效不在Vue的管理实例的范围内-->
<script>
//ES6
const a = `a
ab`; //能够实现自动换行 特殊的引号
//创建组件构造器对象
const cpnConstractor = Vue.extend({
template: `
<div>
<h2>我是1</h2>
<span>我是2</span>
</div>`,
//template是自定义组件的模板
});
//注册组件
// Vue.component("组件的标签名",'定义的组件构造器');
// Vue.component("my-cpn", cpnConstractor); //这种定义的全局组件只要是vue管理的实例内都可以进行引用
const app = new Vue({
el: "#app",
data: {
message: "李加喜",
},
components: {
cpn1: cpnConstractor,
},
//局部的组件 只能够在这个定义的容器里面进行使用
});
</script>
2.2 创建父子组件
<div id="app">
<cpn2></cpn2>
<!--<cpn1></cpn1> 这个里面已经不能在使用cpn1了 因为在这个容器里面只定义了cpn2-->
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建第一个组件构造器(子组件)
const cpnC1 = Vue.extend({
template: `
<div>
<h2>我是标题1</h2>
<p>我是内容, 哈哈哈哈</p>
</div>
`,
});
// 2.创建第二个组件构造器(父组件)
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是标题2</h2>
<p>我是内容, 呵呵呵呵</p>
<cpn1></cpn1>
</div>
`,
// 在这里引入了子组件 那么就可以调用子组件
components: {
cpn1: cpnC1,
},
});
// root组件
const app = new Vue({
el: "#app",
data: {
message: "你好啊",
},
components: {
cpn2: cpnC2,
},
});
</script>
2.3 组件的语法糖
创建全局组件与局部组件
//使用语法糖注册组件
//创建全局组件
<script>
Vue.component("cpn1", {
template: `
<div>
<h2>123</h2>
<h2>456</h2>
</div>
`,
});
//创建局部组件
const app = new Vue({
el: "#app",
data: {
message: "你好啊",
},
components: {
cpn2: {
template: `
<div>
<h2>456</h2>
<h2>123</h2>
</div>
`,
},
},
});
</script>
2.4 模板组件的分离式写法
<div id="app">
<span>{{message}}</span>
<cpn1></cpn1>
<!-- <cpn2></cpn2> -->
</div>
<!-- <script type="text/x-template" id="mycpn">
<div>
<h3>1</h3>
<h3>2</h3>
<h3>3</h3>
</div>
</script> -->
<!--或者-->
<template id="mycpn">
<div>
//最好引入一个根
<h3>{{title}}</h3>
<h3>2</h3>
<h3>3</h3>
</div>
</template>
<script>
Vue.component("cpn1", {
template: "#mycpn",
data() {
return {
title: "456",
};
},
});
const app = new Vue({
el: "#app",
data() {
return {
message: "你好啊",
};
},
components: {
cpn2: {
template: "#mycpn",
},
},
});
</script>
2.5 父组件与子组件之间的通信
父组件向子组件传递数据使用props
子组件向父组件通过事件
在子组件里面定义props
<!--
通过props向子组件传递数据 将props定义在子组件里面
通过事件向父组件传递数据
-->
<div id="app">
<cpn :cmessage="message" :cmovies="movies"></cpn>
</div>
<template id="cpn">
<div>
//必须要有一个根
<ul>
<li v-for="item in cmovies">{{item}}</li>
</ul>
<h2>{{cmessage}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子: props
const cpn = {
template: "#cpn",
// props: ["cmovies", "cmessage"],
//可以自定义props的类型 有很多种定义的方式
props: {
cmessage: {
type: String,
default: "aaaaaaaa",
required: true,
//这个属性是必须要进行传递的
},
cmovies: {
type: Array,
default() {
return [];
},
},
},
};
const app = new Vue({
el: "#app",
data: {
message: "你好啊",
movies: ["海王", "海贼王", "海尔兄弟"],
},
components: {
cpn,
},
});
</script>
处理props的驼峰
<script src="../js/vue.js"></script>
<div id="app">
<span>{{message}}</span>
<cpn :cmessage="message" :c-movies="movies"></cpn>
</div>
<template id="mycpn">
<div>//必须要有一个根
<ul>
<li v-for="item in cMovies">{{item}}</li>
</ul>
<h2>{{cmessage}}</h2>
</div>
</template>
<script>
const cpn = {
template: `#mycpn`,
props: {
cmessage: {
type: String,
},
cMovies: {
type: Array,
default() {
return [];
},
},
},
};
const app = new Vue({
el: "#app",
data: {
message: "你好",
movies: ["海王", "海贼王", "海尔兄弟"],
},
components: {
cpn,
},
});
</script>
子组件向父组件传递数据
步骤
- 创建子组件的模板
- 创建子组件来引用子组件模板
- 设置子组件要传递的数据以及自定义子组件的触发的事件
- 在父组件模板里面引用子组件以及子组件的自定义事件
- 在父组件里面设置对应的方法
<!--父组件模板-->
<div id="app">
<cpn @item-click="cpnClick"></cpn>
</div>
<!--子组件模板-->
<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: 'aaa', name: '热门推荐'},
{id: 'bbb', name: '手机数码'},
{id: 'ccc', name: '家用家电'},
{id: 'ddd', name: '电脑办公'},
]
}
},
methods: {
btnClick(item) {
// 发射事件 $emit: 自定义事件 并且传递了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>
2.6 插槽的基本使用
包含有名字的插槽和没有名字的插槽
<script src="../js/vue.js"></script>
<div id="app">
<cpn></cpn>
<cpn>
<span>我来取代插槽的内容</span>
</cpn>
<cpn>
<button value="点击">按钮</button>
</cpn>
<hr />
<cpn>
<span slot="ljx">取代有名字的插槽</span>
</cpn>
</div>
<template id="cpn">
<div>
<span>我是不会被取代的</span><br />
<slot>我是一个没有名字的插槽</slot><br />
<slot name="ljx">我是一个有名字的插槽</slot>
</div>
</template>
<script>
Vue.component("cpn", {
template: "#cpn",
});
let app = new Vue({
el: "#app",
data: {
message: "李加喜",
},
});
</script>
编译的作用域
- 在vue实例里面使用的就是引用vue实例的data数据,如果是在子组件里面里面使用的就是子组件的data值
官方准则:父组件模板的所有东西都会在父级作用域内进行编译,子组件模板的所有东西都会在子组件的作用域内进行编译
<div id="app">
<span>{{message}}</span>
<cpn></cpn>
<cpn v-show="isShow"></cpn>
<!-- 关联的是vue实例的数据 -->
</div>
<template id="cpn">
<div>
<h2>我是子组件</h2>
<button v-show="isShow">按钮</button>
<!-- 关联的是子组件的data -->
<!--这个不会被显示 因为设置的是false-->
</div>
</template>
<script>
const app = new Vue({
el: "#app",
data: {
message: "你好",
isShow: true,
},
components: {
cpn: {
template: "#cpn",
data() {
return {
isShow: true,
};
},
},
},
});
</script>
2.作用域插槽
父组件替换插槽的标签,但是由子组件来进行提供内容
<div id="app">
<cpn></cpn>
<cpn>
<!--目的是获取子组件中的pLanguages 使用slot-scope来获取插槽里面设置的数据-->
<template slot-scope="a">
<!--<span v-for="item in slot.data"> - {{item}}</span>-->
<span>{{a.data.join(' - ')}}</span>
</template>
</cpn>
<cpn>
<!--目的是获取子组件中的pLanguages 通过slot_scope来获取绑定的数据-->
<template slot-scope="slot">
<!--<span v-for="item in slot.data">{{item}} * </span>-->
<span>{{slot.data.join(' * ')}}</span>
</template>
</cpn>
<!--<cpn></cpn>-->
</div>
<template id="cpn">
<div>
<!-- 在定义插槽的时候为这个插槽绑定数据 -->
<slot :data="pLanguages">
<ul>
<li v-for="item in pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
message: "你好啊",
},
components: {
cpn: {
template: "#cpn",
data() {
return {
pLanguages: [
"JavaScript",
"C++",
"Java",
"C#",
"Python",
"Go",
"Swift",
],
};
},
},
},
});
</script>