vue组件传值的几种方式

vue组件传值的几种方式

1.Vuex

Vuex是一种转为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的多有组件的状态,并以相应的规则保证状态以一种可预期的方式发生变化。

  • 优点
    • 解决了多层组件之间繁琐的事件传播。
    • 解决了多组件依赖统同一状态的问题。
    • 单向数据流
    • 为Vue量身定做,学习成本不高
  • 缺点
    • 不能做数据持久化,刷新页面就要重制,要做数据持久化可以考虑使用localstorage。
    • 增加额外的代码体积,简单的业务场景不建议使用。

2.EventBus

通过共享一个vue实例,使用该实例的 o n 和 on和 onemit实现书数据传递。

// 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实例,所以容易出现重复触发的情景,例如:
      1. 多人开发时,A、B两个人定义了同一个事件名。
      2. 两个页面都定义了同一个事件名,并且没有用$off销毁(常出现在路由切换时)。
      3. 在for出来的组件里注册。
    • 项目一大用这种方式管理事件会十分混乱,这时候建议用vuex。

3.props和 e m i t / emit/ emit/on

父组件向子组件传值
//子组件
//通过props接收父组件传递的数据
Vue.component('blog-post', {
  props: ['title'],
  template: '

{{ title }}

'
}) //父组件 //父组件中注册子组件并传递数据 <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(事件名,参数)
-或者是this.
emit()<br/>this.
listteners.事件名(参数)

你可能感兴趣的:(vue)