components
├── Grandson1.vue // 孙子1
├── Grandson2.vue // 孙子2
├── Parent.vue // 父亲
├── Son1.vue // 儿子1
└── Son2.vue // 儿子2
Parent.vue
<template>
<div>
父组件:{
{
mny}}
<Son1 :mny="mny"></Son1>
</div>
</template>
<script>
import Son1 from "./Son1";
export default {
components: {
Son1
},
data() {
return {
mny: 100 };
}
};
</script>
Son1.vue
<template>
<div>子组件1: {
{
mny}}</div>
</template>
<script>
export default {
props: {
mny: {
type: Number,
default: 1
}
}
};
</script>
当传递的属性过多时,可用 $attrs
(在下面进行了说明)
Parent.vue
<template>
<div>
父组件:{
{
mny}}
<Son1 :mny="mny" @input="change"></Son1>
</div>
</template>
<script>
import Son1 from "./Son1";
export default {
methods: {
change(mny) {
this.mny = mny;
}
},
components: {
Son1
},
data() {
return {
mny: 100 };
}
};
</script>
Son1.vue
<template>
<div>
子组件1: {
{
mny}}
<button @click="$emit('input',200)">更改</button>
</div>
</template>
<script>
export default {
props: {
mny: {
type: Number,
default: 1
}
}
};
</script>
用于场景:父组件传递的属性子组件想修改
<Son1 :mny.sync="mny"></Son1>
<!-- 触发的事件名 update:(绑定.sync属性的名字) -->
<button @click="$emit('update:mny',200)">更改</button>
等同于:value+@input事件的结合
<Son1 v-model="mny"></Son1>
<template>
<div>
子组件1: {
{
value}} // 触发的事件只能是input
<button @click="$emit('input',200)">更改</button>
</div>
</template>
<script>
export default {
props: {
value: {
// 接收到的属性名只能叫value
type: Number
}
}
};
</script>
v-model 与 .sync 的区别
两者的目的都是实现组件与外部数据的双向绑定。v-model 是 .sync 的一种体现(prop是value
,vm.$emit('update:input')
)。
v-model只能在表单元素像单选框/输入框等类型的控件中实现双向绑定,但是如果用在一个组件上,就无法实现双向绑定,因为从本质上说,他就是绑定value
值,监听input
事件,总的来说,v-model 倾向于 ‘value’。.sync 倾向于 ‘change
’,是父组件获取子组件状态的一种快捷方式,是一种update
操作,事件名称也相对固定 update:xx
。
将要传递的数据放到URL后面,跳转到另外的组件时直接获取url字符串获取想要的参数。
// router index.js 动态路由
{
path:'/params/:Id',
component:Params,
name:Params
}
// 跳转路由
<router-link :to="/params/10">跳转路由</router-link>
在跳转后的组件中用$route.params.id
去获取到这个id参数为10,但这种只适合传递比较小的数据,数字之类的。
在组件之外定义一个bus.js 作为组件间通信的桥梁,适用于比较小型不需要vuex 又需要兄弟组件通信的
1、bus.js中添加
import Vue from 'vue'
export default new Vue
2、组件中调用bus.js通过自定义事件传递数据
import Bus from './bus.js'
export default {
methods:{
bus () {
Bus.$emit('msg', '传给兄弟组件的')
}
}
}
3、兄弟组件中监听事件接受数据
import Bus from './bus.js'
export default {
mounted () {
Bus.$on('msg', (e) => {
console.log(e)
})
}
}
vuex是vue的集中状态管理工具,对于大型应用统一集中管理数据
规范:
继续将属性传递
Parent.vue中
<Son1 :mny="mny" @input="mny => this.mny = mny"></Son1>
Son1.vue中
<Grandson1 :value="value"></Grandson1>
Grandson1.vue
<template>
<div>
孙子:{
{
value}}
<!-- 调用父组件的input事件 -->
<button @click="$parent.$emit('input',200)">更改</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number
}
}
};
</script>
如果有很多父级,即层级很深,parent.parent… ,那么可以封装一个$dispatch
方法向上进行派发
Vue.prototype.$dispatch = function (eventName, value) {
let parent = this.$parent;
while (parent) {
parent.$emit(eventName, value)
parent = parent.$parent
}
}
Grandson1.vue
<button @click="$dispatch('input', 200)">更改儿子1 value数据</button> // 此刻的input其实为parent.vue中的
既然能够向上派发也能向下派发
// 向下派发
Vue.prototype.$broadcast = function broadcast(componentName, eventName, data) {
this.$children.forEach((child) => {
const name = child.$options.name
console.log(name)
// 组件名与传入componentName一致
if (name === componentName) {
// 子组件触发eventName事件
child[eventName](data)
} else {
broadcast.call(child, eventName, data) // eslint-disable-line
}
})
}
Grandson1.vue
孙子的年龄:{
{
age}}
export default {
data() {
return {
age: 10
}
},
methods: {
broadcastTest (val) {
this.$nextTick(() => {
alert(val)
this.age = val
})
}
}
}
Son1.vue
<button @click="$broadcast('Grandson1','broadcastTest', 19)">更改孙子年龄</button>
批量向下传入属性
<Son2 name='Tom' age='19'></Son2>
<!-- 可以在Son2组件中使用$attrs属性,可以将属性继续向下传递 -->
儿子2:{
{
$attrs.name}}
<Grandson2 v-bind="$attrs"></Grandson2>
<!--- Grandson2.vue -->
<template>
<div>
孙子:{
{
$attrs}}
</div>
</template>
批量向下传方法
<Son2 name='AA' age='19' @click='() => {this.mny = 500}'></Son2>
<!-- 可以在son2组件中使用listeners属性,可以将方法继续向下传递 -->
<Grandson2 v-bind='$attrs' v-on='$linsteners'></Grandson2>
<button @click='$listeners.click()'>更改</button>
只需要向后台注入组件本身,后代组件中可以无视层级任意访问组件中的状态。
在父级中注入数据
Son2.vue
provide () {
return {
parentMsg: '这是儿子2'}
}
之后在想调用的子组件中使用用 inject 引入。
在任意子组件中可以注入父级数据
Grandson2.vue
<p>动态设置的son2的值然后传入到孙子的值: {
{
parentMsg}}</p>
export default {
inject: ['parentMsg'] // 会将数据挂载到当前实例上
}
实际上,可以把依赖注入看做一部分"大范围有效的prop",除了:
1、祖先组件不需要知道哪些后代组件使用它提供的属性
2、后代组件不需要知道被注入的属性来自哪里
提示:provide 和 inject 绑定并不是可响应的。然而如果传入的是一个可监听的对象,那么其对象的属性还是可响应的