vue组件通信及vuex原理解析

2020-04-24  本文已影响0人  xuyz

组件传值

组件是 vue.js强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系:

父传子

  1. props
// 父组件:
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
    
// 子组件
props: { msg: String } 
  1. $attrs 子组件未在props中声明的属性

inheritAttrs: false

<!-- 父组件 -->
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" foo="foo"/>
  
<!-- 子组件 -->
<p>{{$attrs.foo}}</p>
  
<input v-bind="$attrs"/> // placeholder type ...
  1. $refs: 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
    // 子组件
    export default {
      data () {
        return {
          title: 'I am hw componet'
        }
      },
      methods: {
        say () {
          alert('Hello');
        }
      }
    }
    
    // 父组件
    <HelloWorld :msg="msg" foo="foo" @changeMsg="changeMsg" ref="hw" />
    
     mounted () {
          const hw = this.$refs.hw;
          console.log(hw.title);  // I am hw componet
          comA.sayHello();  // 弹窗 Hello
    }
  1. $parent / $children:访问父 / 子实例

$children子元素不保证顺序

子传父

$emit$on

    // 子组件
    this.$emit('changeMsg')
    
    // 父组件
    <HelloWorld :msg="msg" foo="foo" @changeMsg="changeMsg"/>
    
    changeMsg() {
        this.msg = 'hello world!'
    }

兄弟传值: 通过共同的祖辈组件搭桥,parent或root

// brother1
this.$parent.$on('foo', handle)
// brother2
this.$parent.$emit('foo')

祖代传值

provideinject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。原理解析

【注意】:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的

provide () {
    return {
      bar: 'provide value'
    }
}

// inject: ['bar']
inject: {
  bar: {
      type: string,
      default: ''
  }
}

Vuex核心概念

  1. state
  1. getter
  1. mutation
  1. action
  1. module

Vuex 源码解析

 // vuex.js 实现commit dispatch getter方法

 var Vue
// 实现install方法
function install(_Vue) {
   Vue = _Vue
   Vue.mixin({
       beforeCreate() {
           if (this.$options.store) { // vue的原型上挂载store(Store的实例)
               Vue.prototype.$store = this.$options.store
           }
       }
   })
}
// 实现Store类
class Store {
   constructor(options) {
       this.state = new Vue({
           // 实现state响应化
           data: options.state
       })

       this.mutations = options.mutations || {}
       this.actions = options.actions || {}
       options.getters && this.handleGetters(options.getters)
   }

   commit = (type, arg) => {
       this.mutations[type](this.state, arg)
   }

   // dispatch方法接受一个上下文执行环境,注意与commit区分
   dispatch(type, arg) {
       this.actions[type]({
           state: this.state,
           commit: this.commit,
           getters: this.getters
       }, arg)
   }

   handleGetters(getters) {
       this.getters = {}
       Object.keys(getters).forEach(key => {
           // 利用defineProtperty将getters的执行结果映射成对象
           Object.defineProperty(this.getters, key, {
               get: () => {
                   return getters[key](this.state)
               }
           })
       })
   }
}

export default {
   Store,
   install
}
上一篇 下一篇

猜你喜欢

热点阅读