vue组件传值的几种方式
1.Vuex
Vuex是一种转为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的多有组件的状态,并以相应的规则保证状态以一种可预期的方式发生变化。
- 优点
- 解决了多层组件之间繁琐的事件传播。
- 解决了多组件依赖统同一状态的问题。
- 单向数据流
- 为Vue量身定做,学习成本不高
- 缺点
- 不能做数据持久化,刷新页面就要重制,要做数据持久化可以考虑使用localstorage。
- 增加额外的代码体积,简单的业务场景不建议使用。
2.EventBus
通过共享一个vue实例,使用该实例的 o n 和 on和 on和emit实现书数据传递。
// bus.js文件
import Vue from 'vue'
export default new Vue({})
// component-a.js文件
import bus from './bus.js'
export default {
created () {
bus.$on('event-name', (preload) => {
// ...
})
}
}
// component-b.js文件
import bus from './bus.js'
export default {
created () {
bus.$emit('event-name', preload)
}
}
- 优点
- 解决了多层组件之间繁琐的事件传播。
- 使用原理十分简单,代码量少。
- 缺点
- 由于是都使用一个Vue实例,所以容易出现重复触发的情景,例如:
- 多人开发时,A、B两个人定义了同一个事件名。
- 两个页面都定义了同一个事件名,并且没有用$off销毁(常出现在路由切换时)。
- 在for出来的组件里注册。
- 项目一大用这种方式管理事件会十分混乱,这时候建议用vuex。
- 由于是都使用一个Vue实例,所以容易出现重复触发的情景,例如:
3.props和 e m i t / emit/ emit/on
父组件向子组件传值
//子组件
//通过props接收父组件传递的数据
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
//父组件
//父组件中注册子组件并传递数据
<blog-post title="My journey with Vue"></blog-post>
子组件向父组件传值
//子组件中通过事件触发父组件自定义的事件on-change
<span class="jump" @click="jumpPage(1)">1</span>
<script>
...
methods:{
jumpPage(page) {
this.myCurrent_page = page;
this.$emit('on-change', this.myCurrent_page);
}
}
...
</script>
//父组件
<Page ref="pages" :pages="pages2" @on-change="pageSize2"></Page>
<script>
...
methods:{
pageSize2(page) {
...
}
}
...
</script>
- 优点
- 使用最为简单,也是父子组件传递最常见的方法。
- Vue为给props提供了类型检查支持。
- $emit不会修改到别的组件的同名事件,因为他只能触发父级的事件,这里和event-bus不同
- 缺点
- 单一组件层级一深需要逐层传递,会有很多不必要的代码量。
- 不能解决了多组件依赖统同一状态的问题。
4.provide/inject
在父组件上通过provide提供给后代组件的数据/方法,在后代组件上通过inject来接收被注入的数据/方法。
这种方式传递的属性是非响应式的,所以尽可能传递一些静态属性。
//app.vue
<template>
<div id="app">
<router-view v-if="isRouterAlive"></router-view>
</div>
</template>
export default {
name: "App",
components: {},
provide(){
return {
reload: this.reload
}
},
data(){
return {
isRouterAlive:true
}
},
methods:{
reload(){
this.isRouterAlive = false;
this.$nextTick(function(){
this.isRouterAlive = true;
})
}
}
};
</script>
//子组件
<script>
export default {
inject: ["reload"],
methods:{
todo(){
this.reload()
}
}
}
</script>
- 优点
- 不用像props一层层传递,可以跨层级传递。
- 缺点
- 用这种方式传递的属性是非响应式的,所以尽可能来传递一些静态属性。
- 引用官网的话是
它将你的应用以目前的组件组织方式耦合了起来,使重构变得更加困难。
,我对这句话的理解是用了provide/inject你就要遵循它的组件组织方式,在项目的重构时如果要破坏这个组织方式会有额外的开发成本,其实event-bus也有这个问题。
5. a t t r s / attrs/ attrs/listeners
- $attrs
包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
-父组件给子组件传值可以通过v-bind="KaTeX parse error: Expected '}', got 'EOF' at end of input: …值是以对象形式存在的,直接{{attrs}}进行使用,也可以通过this.$attrs打印出来
- $listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
-父作用域上的所有订阅的事件都可在子组件中被触发
-触发方式可以是
e
m
i
t
(
事
件
名
,
参
数
)
<
b
r
/
>
−
或
者
是
t
h
i
s
.
emit(事件名,参数)<br />-或者是this.
emit(事件名,参数)<br/>−或者是this.listteners.事件名(参数)