vue组件之间的数据传递方法

栏目: JavaScript · 发布时间: 5年前

内容简介:在父组件中,可以通过子组件标签属性的形式将数据或者函数传给子组件,子组件通过props去读取父组件传过来的数据引用类型的props,我们可以在子组件中直接修改引用类型属性的值(如:this.obj.id='3',会生效),但是不能直接改变引用类型存储的地址值(如:this.obj = {id: '3'}),会发出警告。虽然子组件可以直接修改父组件的状态值,但我们不建议这样做,我们希望所有的 prop 都使得其父子 prop 之间形成了一个

(1)props属性:

在父组件中,可以通过子组件标签属性的形式将数据或者函数传给子组件,子组件通过props去读取父组件传过来的数据

  • 用法

    • 父组件传数据给子组件:

      • 一般的属性值都是用来给子组件展示的

    • 子组件传数据给父组件

      • 属性值为函数类型的,一般是用来子组件向父组件传递数据,子组件通过调用父组件传过来的函数,可以修改父组件的状态数据

  • 缺点:

    • 隔层组件间传递: 必须逐层传递(麻烦)

    • 兄弟组件间: 必须借助父组件(麻烦)

  • 注意:

//子组件获取父组件传过来的值
props: {
    obj: {//obj为{id:'2'}
       type: Object
     }
}复制代码

引用类型的props,我们可以在子组件中直接修改引用类型属性的值(如:this.obj.id='3',会生效),但是不能直接改变引用类型存储的地址值(如:this.obj = {id: '3'}),会发出警告。

虽然子组件可以直接修改父组件的状态值,但我们不建议这样做,我们希望所有的 prop 都使得其父子 prop 之间形成了一个 单向下行绑定 :父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

脏数据问题: 如v-model是实现了双向绑定,通过v-model更改数据,会更改父组件的数据,导致脏数据

解决方法:

利用计算属性的set和get,在set中需实现子组件调用父组件的方法,确保数据流向是单向的

computed:{
    msg: {
        get(){
            return this.data
        },
        set(){
            this.$emit('EventName', this.data)
        }    
}}复制代码

(2)vue自定义事件:

  • 方式1: 给子组件标签绑定事件监听

    • 子组件向父组件的通信方式

      • 功能类似于function props

      • 通过在 父组件 中给子组件标签绑定自定义事件的监听,再由子组件触发事件,实现子组件向父组件传递数据的方法,事件名必须一致,且不能有大写字母, v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的)

        // 方式一: 通过v-on绑定
        <component @delete_todo="deleteTodo"/>
        // 方式二: 通过$on()绑定
        this.$refs.xxx.$on('delete_todo', function (todo) {
        this.deleteTodo(todo)})​
        通过this.$emit('delete_todo', todo)触发事件复制代码
    • 不适合隔层组件和兄弟组件间的通信

    • 注意:

      • 在组件标签上绑定事件,会被解析为vue自定义事件

      • 在普通的标签上绑定事件,会被解析为DOM事件

        <--!     
        表示在组件component绑定了一个名为click的vue自定义事件,
        相当于做了vm.$on('click',fn)    
        注意:不是常规理解的点击事件,这里与点击无关,只是名字刚好是click,
        当然实际操作中不建议取这类特殊的名字 
        -->
        <component @click="fn"/>
        <--! 表示在div上绑定一个click的点击事件,是DOM事件 -->​
        ​<div @click="fn"/>复制代码
  • 方式2: 通过单独的vm对象绑定监听/分发事件

    • 任意组件间通信(类似于pubsub)

      • 创建一个公用的vm对象

      import Vue from 'vue'​export default new Vue()复制代码
      • 在接收消息的组件,绑定监听

      import vm from './vm.js'​mounted(){
          vm.$on('delete_todo', function (todo) {
              this.deleteTodo(todo)
          })}复制代码
      • 在发送消息的组件,触发事件

      vm.$emit('delete_todo', todo)复制代码
    • 事件总线(EventBus),其实跟上面的用法一样,这里是把vm实例绑在了Vue的显示原型上

      //点击任意一个组件,其他组件的值跟着变化,利用总线去实现兄弟之间的通信
      Vue.prototype.bus = new Vue()
      var vm = new Vue({
          el:"#app"
          })    
      //v-a组件
      Vue.component('v-a', {
          template:'<div @click="handle">{{msg}}</div>',
          data(){
              return {
                  msg: 'v-a'
              }
          },
          mounted () {
              //绑定事件监听
              this.bus.$on('bus',(msg)=>{
                  this.msg = msg
              })
          },
          methods: {
              handle () {
                  //触发事件
                  this.bus.$emit('bus', this.msg)
              }
          }})
      //v-b组件
      Vue.component('v-b', {
          template:'<div @click="handle">{{msg}}</div>',
          data(){
              return {
                  msg: 'v-b' 
             }
          },
          mounted () {
              //绑定事件监听
              this.bus.$on('bus',(msg)=>{
                  this.msg = msg
              })
          }, 
         methods: {
              handle () {
                  //触发事件 
                 this.bus.$emit('bus', this.msg)
              }
          }})复制代码

(3) 消息的订阅和发布(pubsub)

  • 适用于任何关系的组件间的通信

  • 缺点:相对于vuex,管理不够集中

  • 用法:

    • 引入pubsub-js库

    • 在接收消息的组件订阅消息(subscribe)

      PubSub.subscribe('name',(name,data)=>{})复制代码
    • 在发送消息的组件发布消息 ( publish)

      PubSub.publish('name',data)复制代码
  • 其他用法可以参考官方API文档,这里不细说

(4)vuex

vuex是专门为vue.js应用程序定义的状态管理模式,当多个组件需要共享数据时,我们一般用vuex去管理状态数据,实现多个组件间的相互通信

vue组件之间的数据传递方法

vuex的核心

  • state:存放数据

  • mutations:修改数据

  • actions:提交mutation,修改数据

  • getters:存放数据,类似于vue的计算属性

知道了这几个核心概念后,我们还需要知道怎么合理使用他们

  • 如何从仓库store读取数据

    • state

      从store的实例中我们可以通过store.state去获得状态数据,为了使得store可以全局使用,我们需要通过Vue.use(Vuex),将vuex注给所有vue子的组件,Vue.use回去调用插件的install方法,将stroe绑到Vue.prototype,这样Vue的实例对象都能通过vm.store获取或操作仓库的数据组件内通过this.$store.state可以获得

      state:{    
       data: 0
      }复制代码
    • getters

      有些状态熟悉需要根据其他状态属性计算而动态获得,一般都是存在getters中,组件通过调用this.$store.getters

      Getter 接受 state 作为其第一个参数

      getters:{
          data2(state){
              return state.data+1
          }
      }复制代码
  • 如何修改仓库store的数据

    • mutations (同步修改)

      更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,接受 state 作为第一个参数 ,mutation接收提交载荷,第二个参数为载荷,在大多数情况下,载荷应该是一个对象 ,这样可以接收多个数据

      mutations:{
          mutationType:(state,data)=>{
              state.data = data
          }
      }复制代码
    • actions (异步修改)

      在action中提交mutation,组件通过store.dispatch触发

      因为vue的调试 工具 无法检测到mutations的异步变化,所以我们如果需要异步修改状态数据,一般是放在action去异步获取到数据后再提交mutation,确保vue的调试工具可以检测到,mutation的变化

  • 注意点

    当组件需要给vue中的状态数据添加属性时,通过obj.的形式无法实现

    因为Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:

    1. 我们最好提前在 store 中初始化好所有所需属性。

    2. 当需要在对象上添加新属性时,我们应该

    • 使用 Vue.set(obj, 'newProp', 123) , 或者

    • 以新对象替换老对象。例如,利用 stage-3 的对象展开运算符,我们可以这样写:

    state.obj = { ...state.obj, newProp: 123 }复制代码
  • 优化

    • import {mapState,mapGetters,mapMutations,mapActions} from "vuex";使得在使用vuex时,组件可以写的更加的简洁

    • 数据比较多的时候,使用module

    • 使用常量存放mutation_type

优点:

  • 多组件共享状态(数据的管理)

  • 组件间的关系也没有限制

  • 功能比pubsub强大, 更适用于vue项目

(5) slot插槽

  • 父向子通信

  • 通信是带数据的标签

  • 注意: 标签是在父组件中解析


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Twisted Network Programming Essentials

Twisted Network Programming Essentials

Abe Fettig / O'Reilly Media, Inc. / 2005-10-20 / USD 29.95

Developing With Python's Event-driven Framework一起来看看 《Twisted Network Programming Essentials》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具