7天深入Vue - vue组件之间的通讯与插槽(一)

2021-02-11  本文已影响0人  申_9a33

常用组件之间的通讯

1.props

props:{
 title:{
   type:String, // 类型 String,Number,Boolean,Array,Object,Date,Function,Symbol
   default:"",  // 默认值 为引用类型时,需要为构造函数
   requred:true  // 是否必填
 }
}

注意props 属性忽略大小写,可以使用‘-’来替换驼峰命名


2.eventBus

class EventBus {
  private busMap: Map<string, Array<Function>>;
  constructor() {
    this.busMap = new Map()
  }

  $emit(name: string, arg: any) {
    const list = this.busMap.get(name)
    if (!Array.isArray(list)) {
      return;
    }

    for (const fn of list) {
      try {
        if (typeof fn != "function") {
          throw new Error("")
        }

        fn(arg);
      } catch (error) {
        console.error(error)
      }
    }

  }

  $on(name: string, cb: Function) {
    if (typeof name !== "string" || typeof cb !== "function") {
      throw new Error("参数类型错误")
    }

    let list = this.busMap.get(name)
    if (!list) {
      list = []
      this.busMap.set(name, list)
    }

    list.push(cb)
  }

  $off(name: string, cb: Function) {
    const list = this.busMap.get(name)
    if (!Array.isArray(list)) {
      return
    }

    const index = list.findIndex(fn => cb === fn)
    if (index !== -1) {
      list.splice(index, 1)
    }
  }
}

const bus = new EventBus()

3.Vuex

  const state = {
    data:""
  }
  const mutations = {
    changeData(state,v){
      state.data = v
    }
  }
  const actions = {
      fetchData({commit},arg){
          /**...**/
          /**异步代码 的回调 start**/
          commit("changeData",arg)
         /**异步代码 的回调 end**/
      }
  }
  const getters = {
      getData(state){
          return "pre"+state.data 
      }
  }
  export default new Vuex.Store({
  modules: {
     dataStore:{
        state ,
        mutations,
        actions,
        getters
     }
  }
})
  import { mapGetters, mapActions, mapMutations } from "vuex";
  export default {
    computed:{
      ...mapGetters({
        data:getters
      })
    },
    methods:{
      ...mapActions([
        "fetchData"
      ]),
      ...mapMutations([
        "changeData"
      ])
    }
  }

4.$parent (可以用来给两个子组件进行通讯,发布订阅模式)

  /**子组件1**/
  this.$parent.$emit("event-from-children1",value)

/**子组件2**/
  this.$parent.$on("event-from-children1",v=>{
    console.log(v)
  })

5.$children (父组件可以直接访问子组件的方法和数据)

this.$children[0].xx() // 访问子组件0的方法 注意存在异步组件时,组件顺序不可知

6.$root (特殊的parent,使用一样 )


7.$refs (可以拿到指定的children,可以访问子组件的实例)

/**标签**/
<from ref="from"/>

/**调用**/
 this.$refs["from"].xx()

8.provide/inject (依赖注入)

/**父组件**/

  provide() {
    return {
      from: this, // 注入自己,子组件通过from 拿自己想拿的数据
    };
  },
/**任意子组件**/

inject: ["from"],
/**or**/
inject:{
  par:{from:"from"}
}

9.$attrs (用于父组件直接给子组件传值,class 和 style 的其他数据会默认转移到子组件的最外层标签之上)

inheritAttrs: false 可以禁止转移到子组件的最外层标签

  /**父组件**/
<Item label="用户名" prop='username'>
/**item 组件**/
console.log(this.$attrs.label)
console.log(this.$attrs.prop)

10.$listeners (子组件不处理的事件,传递给父组件处理,或者说父组件传递给子组件处理函数)

    <div id="app">
      <child1
        :p-child1="child1"
        :p-child2="child2"
        :p-child-attrs="1231"
        v-on:test1="onTest1"
        v-on:test2="onTest2">
      </child1>
    </div>
   <script>
      Vue.component("Child1", {
        inheritAttrs: true,
        props: ["pChild1"],
        template: `
        <div class="child-1">
        <p>in child1:</p>
        <p>props: {{pChild1}}</p>
        <p>$attrs: {{this.$attrs}}</p>
        <hr>
        <child2 v-bind="$attrs" v-on="$listeners"></child2></div>`,
        mounted: function() {
          this.$emit("test1");
        }
      });
      Vue.component("Child2", {
        inheritAttrs: true,
        props: ["pChild2"],
        template: `
        <div class="child-2">
        <p>in child->child2:</p>
        <p>props: {{pChild2}}</p>
        <p>$attrs: {{this.$attrs}}</p>
          <button @click="$emit('test2','按钮点击')">触发事件</button>
        <hr> </div>`,
        mounted: function() {
          this.$emit("test2");
        }
      });
      const app = new Vue({
        el: "#app",
        data: {
          child1: "pChild1的值",
          child2: "pChild2的值"
        },
        methods: {
          onTest1() {
            console.log("test1 running...");
          },
         onTest2(value) {
            console.log("test2 running..." + value);
          }
        }
      });
    </script>

插槽

/**子组件定义插槽**/

/*具名插槽*/
<slot name="header"></slot>

/*匿名插槽*/
<slot></slot>

/*作用域插槽*/
 <slot name="cell" :item="item" :index="index"></slot>
/**父组件使用插槽**/
/*具名插槽*/
<template v-slot:header>...</template>

/*匿名插槽*/
<template>...</template>

作用域插槽
 <template v-slot:cell="{ item, index }">...</template>
上一篇下一篇

猜你喜欢

热点阅读