关于前端:vue组件之间的通信

6次阅读

共计 3822 个字符,预计需要花费 10 分钟才能阅读完成。

阐明:上面我总结了比拟罕用的 vue 组件之前通信的形式,最近筹备面试,所以有些总结贴上来分享

props 和 $emit

只有父子关系才能够用这种形式,父组件向子组件传递参数用 props,子向父传递应用触发 $emit 自定义事件

  1. props

    <!-- parent.vue, 能够传递 ` 动态 ` 的 props 和 ` 动静 ` 的 props, 动态的参数只能是个 String 类型的,如果是其余类型的肯定要记得加 `:` 来示意这是一个 js 表达式而不是一个字符串 -->
    <Child :name="name" :age="18" address="xxxxx"></Child>
    ...
    data () {
        return {name: 'marry'}
    }
    
    <!-- 传一个参数所有 props, 尽管目前我没有这个需要,应用不带参数的 v-bind -->
    <blog-post v-bind="post"></blog-post>
    post: {
      id: 1,
      title: 'My Journey with Vue'
    }
    // 等价于上面
    <blog-post
      v-bind:id="post.id"
      v-bind:title="post.title"
    ></blog-post>
    
    
    <!-- child.vue -->
    ...
    // 以字符串数组模式列出的 prop
    props: ['name', 'age', 'address']
    
    //prop 验证, 当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的正告
    // 留神:以下类型不能写成 'String' 这种带引号的模式
    props: {// 根底的类型查看 (`null` 和 `undefined` 会通过任何类型验证)
        propA: Number,     
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {return { message: 'hello'}
          }
        },
        // 自定义验证函数
        propF: {validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        }
    }
    // 留神那些 prop 会在一个组件实例创立之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
  2. $emit

    <!-- parent.vue -->
    <Child @my-event="myEvent"></Child>
    ...
    methods: {myEvent(name){this.name = name}
    }
    
    <!-- child.vue -->
    <div>
      <button @click="$emit('my-event', name)"></button>
    </div>
    // 应用自定义事件将子组件的值抛给父组件 

地方事件总线 bus

用于解决跨级和兄弟组件通信问题,奇妙的应用一个公共的 vue 实例,利用 $on, $emit, $off(移除自定义事件监听器)

办法一:

能够在 main.js 中,在 Vue 的原型上挂载一个公共的 Vue 实例 $bus,这样全局任何一个中央都能够应用

Vue.prototype.$bus = new Vue()

而后在须要的中央注册自定义事件和接管参数的回调函数

this.$bus.$on('changeName', name => {this.name = name})

在须要扭转的时候触发事件并抛出参数

this.$bus.$emit('changeName', 'wzj')

办法二:

定义一个 util.js 文件

import Vue from 'vue'

const bus = new Vue()
export default bus

在须要用到 bus 的文件中引入

import bus from '../util'  // 文件门路不肯定

// 在一个文件定义事件
bus.$on('changeName', name => {this.name = name})

// 另一个文件抛出参数
bus.$emit('changeName', 'wzj')

vuex

对于我的项目比较复杂,多组件共享状态,不同层级须要通信

外围概念:

state, getter, mutation, action, module

//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export dafault new Vuex.Store({
  state: {
    name: '',
    age: 0
  },
  getters: {tranName(state){return 'name:' + state.name}
  },
  mutations: {changeName(state, name){state.name = name}
  },
  /*Action 函数承受一个与 store 实例具备雷同办法和属性的 context 对象,因而你能够调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters */
  actions: {   // 异步函数,但还是要通过提交 commit 触发 mutations 函数操作 state
    changeName(context, name){context.commit('changeName', name)
    }
  },
  modules: {}})

在组件中应用

办法一:

// 拜访 state 属性
this.$store.state.name
// 拜访 getters 属性
this.$store.getters.tranName
// 拜访 mutations
this.$store.commit('changeName', 'wzj')
// 拜访 actions
this.$store.dispatch('changeName', 'wzj')

办法二:应用辅助函数映射到本地,这里只列举了简便的形式,更多查阅官网吧

import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
//state 和 getters 映射到本地的 computed 属性中,作为计算属性应用
computed: {...mapState(['name', 'age']),
  ...mapGetters(['tranName'])
}

//mutations 和 actions
methods: {// 将 `this.changeName()` 映射为 `this.$store.commit('changeName')`
  ...mapMutations(['changeName']) 
  // 将 `this.changeName()` 映射为 `this.$store.dispatch('changeName')`
  ...mapActions(['changeName'])
}

$attrs 和 $listeners

父组件与后辈组件,用以上办法有点大材小用或者第一种有些不不便

  • $attrs 蕴含了父作用域中不作为 prop 被辨认 (且获取) 的 attribute 绑定 (classstyle 除外 )。当一个组件没有申明任何 prop 时,这里会蕴含所有父作用域的绑定 (classstyle 除外 ),并且能够通过 v-bind="$attrs" 传入外部组件。
  • $listeners 蕴含了父作用域中的 (不含 .native 润饰器的 ) v-on 事件监听器。它能够通过 v-on="$listeners" 传入外部组件——在创立更高层次的组件时十分有用。

例子:

//app.vue
<div>
  <One name="wzj" :age="age" address="xian" @changeAge="changeAge"></One>
</div>
...
data(){
  return {age: 10}
},
methods: {changeAge(age){this.age = age}
}

//one.vue
<div>
  <div> 姓名:{{name}}</div>
  <div> 年龄:{{age}}</div>
  <Two v-bind="$attrs" v-on="$listeners"></Two>
  <button @click="change"> 点我 2 </button>
</div>
...
props: ['name', 'age'],

//two.vue
<div>
  <div>{{address}}</div>
  <button @click="change"> 点我 2 </button>
</div>
...
props: ['address'],    // 用 $attrs 传递到最初的属性,在应用的时候还是要申明 props
methods: {change(){this.$emit('changeAge', 30)
  }
}

了解 :其实先人组件的属性和事件还是一层层往下传,不过用 $attrs 和 $listeners 优化和简便了传递过程中书写,而且在传递的过程中,任何一个申明了 $listeners 的组件都能够触发外面的所有事件,而申明了 $attrs 的组件只能应用之前未用 props 申明的剩下的属性。

正文完
 0