vue 听说你很会传值?
DIVMonster 人气:0
# 前置
大小 vue 项目都离不开组件通讯, 在这里总结一下vue组件通讯方式并列出, 都是**简单**的例子. 适合像我这样的小白。如有错误,欢迎指正。
> 温馨提示: 下文没有列出 `vuex`, `vuex` 也是重要的组件通讯方式。
# props
- 最常用的组件通讯方式
- 值可以是数组或对象,使用对象时可以配置高级选项,如类型检测、自定义验证和设置默认值
- 方向:父 -> 子
**Son.vue**
```js
export default {
props: {
text: {
type: String,
required: true,
},
},
mounted() {
console.log(this.text) // 我是父组件提供给子组件的值
},
}
```
**App.vue**
```
```
# \$refs
- 常用的方式
- 返回注册过 `ref` 特性的所有 DOM 元素和组件实例
- 可以用来操作 DOM
- 可以用来传值
- 方向:子 -> 父
**Son.vue**
```js
export default {
methods: {
sonFunc() {
console.log('我是子组件的值')
},
},
}
```
**App.vue**
```
```
> 控制台打印: 我是子组件的值
# \$emit
- `$emit` 用来触发当前实例上的事件
- 方向:父 -> 子
- 参数一:来触发的当前实例上的事件函数
- 参数二:附加参数,传给监听器回调
**Son.vue**
```js
export default {
mounted() {
this.$emit('customFunc', '我是子组件传给父组件的值')
},
}
```
**App.vue**
```
```
# @update
- 需要配合 `.sync` 使用
- 与上面的 `$emit` 写法类似
- 不同之处在于`$emit` 的第一个参数不在是当前实例上的事件函数
- 方向:子 -> 父
**Son.vue**
```
export default {
mounted() {
this.$emit("update:text", '我是子组件传给父组件的值')
}
}
```
**App.vue**
```
```
接下来看下面的写法,上面这种写法是对如下方式的简写, 或者称之为语法糖。可以不借助 `.sync`。
**Son.vue**
```
export default {
mounted () {
this.$emit('update:text','我是子组件传给父组件的值')
}
}
```
**App.vue**
```
(this.value = v)" />
import Son from "./componentshttps://img.qb5200.com/download-x/dispatch/Son"
export default {
mounted() {
console.log(this.value) // 我是子组件传给父组件的值
}
}
```
# v-model
- `v-model` 常用来给 input 实现双向数据绑定
- `v-model` 也可以用来传值
- 有局限性,只能传 `input` `value`
```
```
等价于:
```
```
接下来看如何通过 `v-model` 传值。
**Son.vue**
```js
```
**App.vue**
```
```
![](https://img2020.cnblogs.com/blog/1501373/202003/1501373-20200326181514988-1334992321.png)
# \$parent \$childred
- \$parent: 父实例,如果当前实例有的话
- \$children: 当前实例的直接子组件
- \$parent \$childred 通过封装可以实现不同方向的传值
> `$children` 并不保证顺序,也不是响应式的。可以使用一个数组配合 `v-for` 来生成子组件,使用 `Array` 作为真正的来源。
**App.vue**
```js
export default {
data() {
return {
value: '我是父组件的值',
}
},
```
**Son.vue**
```js
export default {
mounted: {
console.log(this.$parent.value) // 我是父组件的值
this.$parent.value = 666
console.log(this.$parent.value) // 666
},
}
```
简单封装一下即可实现`$parent` 配合 `$emit` 实现跨级向上传值。
**main.js**
```js
Vue.prototype.$dispatch = function(event, value) {
let parent = this.$parent
while (parent) {
parent.$emit(event, value)
parent = parent.$parent
}
}
```
这样使用: `this.$dispatch('event',value)`
简单封装一下即可实现`$children` 配合 `$emit` 实现向下传值。
```js
Vue.prototype.$broadcast = function(event, value) {
const broadcast = children => {
children.forEach(child => {
child.$emit(event, value)
if (child.$children) {
broadcast(child.$children)
}
})
}
broadcast(this.$children)
}
```
这样使用: `this.$broadcast('event',value)`
# \$attrs
- 获取父组件通过 `v-bind` 传过去的所有值
- class 和 style 除外
- 可以通过 `v-bind="$attrs"` 传入内部组件
- 只能在 `` 中使用
- 方向:子 -> 父
**App.vue**
```
import Son from './componentshttps://img.qb5200.com/download-x/dispatch/Son'
export default {
name: 'app',
components: {
Son,
},
}
```
**Son.vue**
```
```
**Son.vue**
```html
```
# provide inject
- `provide` 和 `inject` 不推荐直接用于应用程序代码中
- 与 React 的上下文特性很相似。这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效
- `provide` 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作
- `provide` 和 `inject` 绑定并不是可响应的。这是 vue 刻意为之
- 如果你传入了一个可监听的对象,那么其对象的属性还是可响应的
这里有一个简单的示例:
**App.vue**
```
```
**Son.vue**
```js
export default {
inject: ['text'],
mounted() {
console.log(this.text) // 我是父组件的值
},
}
```
# 事件总线
- EventBus 又称为事件总线
- 不是一个具体的 API,EventBus 代表一种思路
- 可以看作 vuex 的究极压缩版
**App.vue**
```
```
**Son.vue**
```js
export default {
mounted() {
this.$EventBus.$on('event', function(v) {
console.log(v)
})
},
}
```
# Observable
- `observable` 可以让一个对象可响应
- vue 内部会用它来处理 data 函数返回的对象
- 返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新
- 可以作为最小化的跨组件状态存储器,用于简单的场景
**store.js**
```js
import Vue from 'vue'
export const store = Vue.observable({ text: '我是store里的' })
export const mutations = {
setText(text) {
store.text = text
},
}
```
**App.vue**
```
import { store, mutations } from '../store'
export default {
mounted() {
console.log(store.text) //我是store里的
mutations.setText('我在App.vue中将你改变')
console.log(store.text) //我在App.vue将你改变
},
}
```
# composition-api
- `composition-api` 包含 vue3 的新特性
- `provide` 和 `inject` 可以实现嵌套组件之间的数据传递
- 这两个函数只能在 `setup` 函数中使用
- 父级组件中使用 `provide` 函数向下传递数据
- 子级组件中使用 `inject` 获取上层传递过来的数据
- 不限层级。
**App.vue**
```
```
**Son.vue**
```
{{$attrs}}
```
![](https://img2020.cnblogs.com/blog/1501373/202003/1501373-20200326181532531-152312591.png)
# \$listener
- 获取父作用域中的 () `v-on` 事件监听器。
- 不含 `.native` 修饰器修饰的时间监听器。
- 可以通过 `v-on="$listeners"` 传入内部组件(孙子组件)。
- 方向:父 -> 子
**App.vue**
```
{{ customVal }}
``` > 父组件可以通过 **ref** 创建响应式数据通过 **provide** 共享给子组件。加载全部内容