1 父=>子 父:msg='msg' 子props
单向数据流,子组件不允许改变props的值,如msg
2 子=>父 子事件里触发事件this.$emit(名 , 参) 父@名='fn' fn(参)
在组件上写event,都是自定义事件
即便: <Son @click='fn'/> 点击不会触发click
要想使用原生click:
父 <Son @click.native='fn'/>
子 (不用写this.$emit)
.native原理:
将@click="$emit('click')"绑定在了子组件的根div上,点击子组件的哪里都会触发(事件委派)
3 非父子
1.全局定义,在main.js文件将bus挂载到vue.prototype上
import Vue from 'vue';
Vue.prototype.bus = new Vue();
2.新建一个bus.js文件,作为*总线,然后再组件引用时调用这个bus.js文件
import Vue from 'vue';
const EventBus = new Vue();
export default EventBus;
一个触发事件 bus.$emit('名' , 参)
一个监听事件 bus.$on( '名' , fn(参) )
4 $attrs 与 $listeners 得到父组件的属性与事件
父组件: <Son type="" titil="" :msg="msg" @click='fn' >
子组件props:['type'] 用this.$attrs {titil="" msg="msg"}
子组件
<p :title="this.$attrs.title" :msg="this.$attrs.msg"></p>
可简写为:<p v-bind="this.$attrs"></p>
$lieteners值为父组件的 自定义事件&&非.native
5 $parent / $children与 ref
ref:用在子组件上,访问组件实例
$parent / $children:访问父 / 子实例
ref
父: <Son ref="comA" /> const a=this.$ref.comA.title
子: data () { return { title: 'Vue.js' } }
$parent / $children
父: <Son /> const a=this.$children.title
子: data () { return { title: 'Vue.js' } }
6 provide/inject
祖先组件=>子孙组件
祖先组件provider来提供变量,子孙组件inject来注入变量。
//provide 是一个对象, inject 是:一个字符串数组
// A.vue
export default {
provide: {
name: '浪里行舟'
}
}
// B.vue
export default {
inject: ['name'],
mounted () {
console.log(this.name); // 浪里行舟
}
}
provide 和 inject 绑定并不是可响应的,A.vue 的 name 如果改变了,B.vue 的 this.name 是不会改变的
实现数据响应式:
provide 是一个函数(返回值为一个对象), inject 是:一个对象,对象的 key 是本地的绑定名
//方法一:提供祖先组件的实例
data () { return { color: 'red' } },
provide() {
return {
theme: this
};
},
//方法二:使用2.6最新API Vue.observable 优化响应式 provide
provide() {
this.theme = Vue.observable({ //向实例this上添加theme对象
color: "blue"
});
return {
theme: this.theme
};
/************
return {
theme: Vue.observable({ color: "blue" });
};
************/
},
methods: {
changeColor(color) {
this.theme.color = color;
}
}
//子孙组件写法一样
<template functional>
<div class="border2">
<h3 :style="{ color: theme.color }">F 组件</h3>
</div>
</template>
<script> export default {
inject: {
theme: {
//函数式组件取值不一样
default: () => ({})
}
}
};
</script>
7 作用域插槽
插槽: 父组件提供代码(html模板) => 子组件的slot => 再显示在父组件上
默认插槽
父:
<div>
<Son></Son>
</div>
子:
<div>
<slot>没插</slot>
</div>
//结果: 没插
父:
<div>
<Son>插了</Son>
</div>
子:
<div>
<slot>没插</slot>
</div>
//结果: 插了
具名插槽 ( 子组件有多个slot )
父:
<Son>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
</Son>
子:
<div>
<slot name="header"></slot>
...
<slot name="footer"></slot>
</div>
作用域插槽
父组件提供代码(html模板)带有子组件的数据 => 子组件的slot => 再显示在父组件上
父:
<Son>
<template v-slot:todo="slotProps" > {{slotProps.user.firstName}} </template>
</Son>
//slotProps 可以随意命名
//slotProps 接取的是子组件标签slot上属性数据的集合所有v-bind:user="user"
//:todo是插槽名(具名插槽), :default是默认插槽
子:
<slot name="todo" :user="user" :test="test"> </slot>
data() {
return {
user:{
lastName:"Zhang",
firstName:"yue"
},
test:[1,2,3,4]
}
},
混入 mixin
重复的js 写在一个单独的js里, 如myMixin
export default{
...
}
引入 import myMixin from './myMixin'
使用 mixins: [ ' myMixin ' ]