目录
- 前言
- 一,组件的使用
- 二,插槽slot
- 三,refs和parent
- 四,父子组件间的通信
- 4.1,父传子 :父传子的时候,通过属性传递
- 4.2,父组件监听自定义事件
- 五,非父子组件的通信
- 六,混入(mixin)
- 最后
前言
上一章博客我们讲解了Vue生命周期,列表过滤,计算属性和监听器
这一章我们来讲Vue组件开发
一,组件的使用
创建组件两种方式
var Header = {
template:'模板' ,
data是一个函数,
methods:功能,
components:子组件们
}//局部声明
Vue.component('组件名',组件对象);//全局注册 等于注册加声明了
组件的分类
- 通用组件(例如表单、弹窗、布局类等) (多个项目都可以复用)
- 业务组件(抽奖、机器分类)(本项目中复用)
- 页面组件(单页面开发程序的每个页面的都是一个组件、只完成功能、不复用)
组件开发三部曲:声明、注册、使用
注意:子组件的命名,如果有驼峰命名,在使用子组件标签时用“-”隔开
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好,{{name}}
<hello></hello>
<saybyebye></saybyebye>
</div>
<template id="myhello">
<div>hello,{{name}}</div>
</template>
</body>
<script src="../js/vue2.7.js"></script>
<script>
// 注册了一个全局组件,名字叫hello
Vue.component('hello',{
template:`#myhello`,
data(){
return{
name:'我是hello'
}
}
})
// 定义一个局部组件
var saybyebye={
template:`<div>你好</div>`
}
var app = new Vue({
el:'#app',
data(){
return{
name:"张三",
}
},
// 注册局部组件
components:{
saybyebye
}
})
</script>
</html>
二,插槽slot
slot就是在声明子组件时给DOM留下的坑位,以便于父组件在使用子组件的时候可以在坑位里动态的插入自己的内容。
并且,坑位是可以命名的,也就是说,子组件在声明的时候命名坑位,方便父组件在指定的坑位中插入内容
slot是动态的DOM
- 插槽的使用:
- 步骤有两步:a.子组件上留坑。b.父组件使用子组件的时候,给坑里赋值.
- 要有父子组件作为前提。
- 目的是让子组件成为动态的组件。
匿名插槽
- 匿名插槽就是在声明的时候没有声明name,会把全部内容都显
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好,{{name}}
<hello></hello>
<saybyebye>
<div>我是插槽的内容</div>
</saybyebye>
</div>
<template id="myhello">
<div>hello,{{name}}</div>
</template>
</body>
<script src="../js/vue2.7.js"></script>
<script>
// 注册了一个全局组件,名字叫hello
Vue.component('hello',{
template:`#myhello`,
data(){
return{
name:'我是hello'
}
}
})
// 定义一个局部组件
var saybyebye={
template:`
<div>
<div>你好</div>
// 插槽内容
<slot></slot>
</div>
`
}
var app = new Vue({
el:'#app',
data(){
return{
name:"张三",
}
},
// 注册局部组件
components:{
saybyebye
}
})
</script>
</html>
具名插槽
- 具名插槽会在声明时,指定name。会在子组件中有选择的进行展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好,{{name}}
<hello></hello>
<saybyebye>
<div slot="niu1">我是插槽的内容</div>
<template #niu2>
<div>你好niu2</div>
</template>
<template v-slot:niu3>
<div>你好niu3</div>
</template>
</saybyebye>
</div>
<template id="myhello">
<div>hello,{{name}}</div>
</template>
</body>
<script src="../js/vue2.7.js"></script>
<script>
// 注册了一个全局组件,名字叫hello
Vue.component('hello',{
template:`#myhello`,
data(){
return{
name:'我是hello'
}
}
})
// 定义一个局部组件
var saybyebye={
template:`
<div>
<slot name="niu1"></slot>
<div>你好niu1</div>
// 插槽内容
<slot name="niu2"></slot>
<slot name="niu3"></slot>
</div>
`
}
var app = new Vue({
el:'#app',
data(){
return{
name:"张三",
}
},
// 注册局部组件
components:{
saybyebye
}
})
</script>
</html>
三,refs和parent
这两个属性的作用是获取到子组件实例数组和父组件实例。
有了实例,就可以很方便的操作组件的属性和方法。
- refs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好{{name}}
<button @click="ouda">打一顿</button>
<Myheader ref="dawa"></Myheader>
</div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
Vue.prototype.$middleBus = new Vue();
var Myheader = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
</div>
`,
data(){
return{
xingming:'林宇豪',
Hp:100,
}
},
}
var app = new Vue({
el:'#app',
data(){
return{
name:'小豪',
}
},
methods:{
ouda(){
console.log("孽子,打一顿");
this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
},
},
components:{
Myheader
}
})
</script>
</html>
- parent
$refs的使用需要,在子元素上通过ref属性声明自己的引用名称
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好,我是{{name}}
<Myheader ref="dawa"></Myheader>
<Myheadererwa ref="erwa" ></Myheadererwa>
</div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
Vue.prototype.$middleBus = new Vue();
var Myheader = {
template:`
<div>
</div>
`,
}
var Myheadererwa = {
template:`
<div>
<button @click="jiao">叫爷爷</button>
</div>
`,
data(){
return{
}
},
methods:{
jiao(){
this.$parent.name="爷爷"
},
},
}
var app = new Vue({
el:'#app',
data(){
return{
name:'小豪',
}
},
components:{
Myheader,
Myheadererwa
}
})
</script>
</html>
四,父子组件间的通信
4.1,父传子 :父传子的时候,通过属性传递
- 在子组件标签中,自定义属性和值
<Myheader ref="header" age="18" :sex="sex"></Myheader>
- 在子组件内部,通过props属性,获取所有的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好{{name}}
<button @click="ouda">打一顿</button>
<button @click="anwei">安慰</button>
<button @click="xiaodao">看看导哥在干嘛</button>
<Myheader ref="dawa"></Myheader>
<Myheadererwa ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
<div id="mydiv"></div>
</div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
Vue.prototype.$middleBus = new Vue();
var Myheader = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
</div>
`,
data(){
return{
xingming:'林宇豪',
Hp:100,
}
},
}
var Myheadererwa = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
<button @click="jiao">叫爷爷</button>
二娃 = {{age}} -- {{nengli}}
</div>
`,
data(){
return{
xingming:'王导',
Hp:0,
}
},
methods:{
see(){
console.log("再看岛国动作片");
},
jiao(){
this.$parent.name="爷爷"
},
},
mounted(){
this.$middleBus.$on('jieshou',val=>{
// 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
console.log(val);
});
},
props:['age','nengli'],
}
var app = new Vue({
el:'#app',
data(){
return{
name:'小豪',
nengli2:"千里眼,顺风耳"
}
},
methods:{
ouda(){
console.log("孽子,打一顿");
this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
// if(this.$refs.dawa.Hp<=0){
// document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
// }
},
anwei(){
console.log("抽了一巴掌,安慰了一下");
this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
},
xiaodao(){
this.$refs.erwa.see()
},
},
components:{
Myheader,
Myheadererwa
}
})
</script>
</html>
4.2,父组件监听自定义事件
<Myheadererwa -parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好{{changname}}
<button @click="ouda">打一顿</button>
<button @click="anwei">安慰</button>
<button @click="xiaodao">看看导哥在干嘛</button>
<Myheader ref="dawa"></Myheader>
<Myheadererwa @to-parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
<div id="mydiv"></div>
</div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
Vue.prototype.$middleBus = new Vue();
var Myheader = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
<button @click="chuanzhi">发送一条信息</button>
</div>
`,
data(){
return{
xingming:'林宇豪',
Hp:100,
}
},
methods:{
chuanzhi(){
this.$middleBus.$emit('jieshou','你好child01,我是child02');
}
}
}
var Myheadererwa = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
<button @click="jiao">叫爷爷</button>
<button @click="happyNewYear">给爷爷拜年</button>
二娃 = {{age}} -- {{nengli}}
</div>
`,
data(){
return{
xingming:'王导',
Hp:0,
}
},
methods:{
see(){
console.log("再看岛国动作片");
},
jiao(){
this.$parent.name="爷爷"
},
happyNewYear(){
// 触发自定义事件
this.$emit('to-parent-event',this.xingming)
}
},
mounted(){
this.$middleBus.$on('jieshou',val=>{
// 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
console.log(val);
});
},
props:['age','nengli'],
}
var app = new Vue({
el:'#app',
data(){
return{
changname:'小豪',
nengli2:"千里眼,顺风耳"
}
},
methods:{
ouda(){
console.log("孽子,打一顿");
this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
// if(this.$refs.dawa.Hp<=0){
// document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
// }
},
anwei(){
console.log("抽了一巴掌,安慰了一下");
this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
},
xiaodao(){
this.$refs.erwa.see()
},
bainian(xingming){
console.log(xingming+"给您拜年了 ");
}
},
components:{
Myheader,
Myheadererwa
}
})
</script>
</html>
五,非父子组件的通信
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好{{changname}}
<button @click="ouda">打一顿</button>
<button @click="anwei">安慰</button>
<button @click="xiaodao">看看导哥在干嘛</button>
<Myheader ref="dawa"></Myheader>
<Myheadererwa @to-parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
<div id="mydiv"></div>
</div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
Vue.prototype.$middleBus = new Vue();
var Myheader = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
<button @click="chuanzhi">发送一条信息</button>
</div>
`,
data(){
return{
xingming:'林宇豪',
Hp:100,
}
},
methods:{
chuanzhi(){
this.$middleBus.$emit('jieshou','你好child01,我是child02');
}
}
}
var Myheadererwa = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
<button @click="jiao">叫爷爷</button>
<button @click="happyNewYear">给爷爷拜年</button>
二娃 = {{age}} -- {{nengli}}
</div>
`,
data(){
return{
xingming:'王导',
Hp:0,
}
},
methods:{
see(){
console.log("再看岛国动作片");
},
jiao(){
this.$parent.name="爷爷"
},
happyNewYear(){
// 触发自定义事件
this.$emit('to-parent-event',this.xingming)
}
},
mounted(){
this.$middleBus.$on('jieshou',val=>{
// 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
console.log(val);
});
},
props:['age','nengli'],
}
var app = new Vue({
el:'#app',
data(){
return{
changname:'小豪',
nengli2:"千里眼,顺风耳"
}
},
methods:{
ouda(){
console.log("孽子,打一顿");
this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
// if(this.$refs.dawa.Hp<=0){
// document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
// }
},
anwei(){
console.log("抽了一巴掌,安慰了一下");
this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
},
xiaodao(){
this.$refs.erwa.see()
},
bainian(xingming){
console.log(xingming+"给您拜年了 ");
}
},
components:{
Myheader,
Myheadererwa
}
})
</script>
</html>
- 创建一个公共组件
Vue.prototype.$middleBus = new Vue();
- 发送方,在公共组件上,触发一个事件
this.$middleBus.$emit('sendMsg','你好child01,我是child02');
- 接收方,监听公共组件上的这个事件,并接受数据
this.$middleBus.$on('sendMsg',val=>{
// 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
this.msg = val;
});
六,混入(mixin)
-
定义
- 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项
-
写法
- 局部
- 定义个混入对象
- 局部
var myMixin = {
data() {
return {
mixinname: '混入姓名',
};
},
mounted() {
console.log('我是混入的组件');
},
};
- 项目
mixins: [myMixin],
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
大家好{{changname}}
<button @click="ouda">打一顿</button>
<button @click="anwei">安慰</button>
<button @click="xiaodao">看看导哥在干嘛</button>
<Myheader ref="dawa"></Myheader>
<Myheadererwa @to-parent-event="bainian" ref="erwa" age="2" :nengli="nengli2"></Myheadererwa>
<div id="mydiv"></div>
</div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
Vue.prototype.$middleBus = new Vue();
var commonMixin = {
data(){
return{
mixinName:'葫芦'
}
},
mounted(){
console.log( "混入对象" +this.mixinName);
}
}
var Myheader = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}---{{mixinName}}
<button @click="chuanzhi">发送一条信息</button>
</div>
`,
data(){
return{
xingming:'林宇豪',
Hp:100,
}
},
methods:{
chuanzhi(){
this.$middleBus.$emit('jieshou','你好child01,我是child02');
}
},
mixins:[commonMixin]
}
var Myheadererwa = {
template:`
<div>
子组件
{{xingming}}--{{Hp}}
<button @click="jiao">叫爷爷</button>
<button @click="happyNewYear">给爷爷拜年</button>
二娃 = {{age}} -- {{nengli}}
</div>
`,
data(){
return{
xingming:'王导',
Hp:0,
}
},
methods:{
see(){
console.log("再看岛国动作片");
},
jiao(){
this.$parent.name="爷爷"
},
happyNewYear(){
// 触发自定义事件
this.$emit('to-parent-event',this.xingming)
}
},
mounted(){
this.$middleBus.$on('jieshou',val=>{
// 使用箭头函数,可以不改变this的指向,仍然和外部的this保持一致,指向child01
console.log(val);
});
},
props:['age','nengli'],
}
var app = new Vue({
el:'#app',
data(){
return{
changname:'小豪',
nengli2:"千里眼,顺风耳"
}
},
methods:{
ouda(){
console.log("孽子,打一顿");
this.$refs.dawa.Hp = this.$refs.dawa.Hp - 10
// if(this.$refs.dawa.Hp<=0){
// document.getElementById("#mydiv").innerHTML="已经死了不能在死了爹"
// }
},
anwei(){
console.log("抽了一巴掌,安慰了一下");
this.$refs.erwa.Hp = this.$refs.erwa.Hp + 10
},
xiaodao(){
this.$refs.erwa.see()
},
bainian(xingming){
console.log(xingming+"给您拜年了 ");
}
},
components:{
Myheader,
Myheadererwa
}
})
</script>
</html>
全局混入
- 定义个混入对象
- 引入使用
Vue.mixin(myMixin);
注意
- 当组件和混入对象含有同名选项时,这些选项将进行“合并”
- 在选项发生冲突时以组件数据优先
- 请谨慎使用全局混入,因为会使实例以及每个组件受影响
最后
祝大家: 愿每个人都能遵循自己的时钟,做不后悔的选择。