Vue学习笔记7:vue3组件化开发(2)-复杂组件通信

179 阅读1分钟

1.provide和inject

父组件

image.png

子组件

image.png

image.png

如果provide中的数据,依赖data,需要将provide写成函数形式

image.png

2.事件总线mitt库

安装mitt库

npm install mitt

创建eventbus.js文件

import mitt from 'mitt'

// 接受emitter对象
const emitter = mitt()

export default emitter

组件通信使用

监听: image.png

触发:

image.png

取消监听: 取消所有监听

emitter.all.clear()

取消某个监听

function foo(){}
emitter.on('wjm',foo)

//可以在destroy中取消监听
emitter.off('wjm',foo)

3.插槽slot

3.1具名插槽

navbar.vue

<template>
  <div class="container">
    <div class="left">
        <slot name="left">left</slot>
    </div>
    <div class="center">
      <slot name="center">center</slot>
    </div>
    <div class="right">
      <slot name="right">right</slot>
    </div>
  </div>
</template>

App.vue

<template>
  <nav-bar>
    <template v-slot:left>
      <div>
        left 中 内容
      </div>
    </template>
    <template v-slot:center>
      <div>
        my name is center
      </div>
    </template>
    <template v-slot:right>
      <div>
        right 中 内容
      </div>
    </template>
  </nav-bar>
</template>

v-slot:xxx可以简写为 #xxx:

<template>
  <nav-bar>
    <template #left>
      <div>
        left 中 内容
      </div>
    </template>
    <template #center>
      <div>
        my name is center
      </div>
    </template>
    <template #right>
      <div>
        right 中 内容
      </div>
    </template>
  </nav-bar>
</template>

3.2动态插槽名

navbar.vue

<template>
  <div class="container">
    <div class="dynamic">
      <slot :name="dynamic"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: '',
  props:{
    dynamic:String
  }
}
</script>

app.vue 通过v-bind传值到子组件,通过[]取值书写#[xxx]

<template>
  <nav-bar :dynamic="name">
    <template #[name]>
      <div>
        dynamic value
      </div>
    </template> 
  </nav-bar>
</template>

<script>
import NavBar from "./components/navbar.vue"

export default {
  name: 'App',
  components: {
    NavBar
  },
  data(){
    return {
      name:'wjm'
    }
  }
}
</script>

3.3作用域插槽

渲染作用域: 父级模板里的所有内容都是在父级作用域编译的; 子模板里的所有内容都是在子作用域编译的;

当我们需要再负作用域中使用子组件的数据时:

childCPn.vue

<template>
  <div class="container">
      <template v-for="(item,index) in names" :key="item">
          <slot :item="item" :index="index"></slot>
      </template>
  </div>
</template>

<script>
export default {
  name: '',
  props:{
      names:{
          type:Array,
          default:()=>[]
      }
  }
}
</script>

app.vue

<template>
  <child-cpn :names = "names">
    <template #default = "name">
      <div>
        <button>{{name.item}}-{{name.index}}</button>
      </div>
    </template>
  </child-cpn>
</template>

<script>
import ChildCpn from './components/childCpn'

export default {
  name: 'App',
  components: {
    ChildCpn
  },
  data(){
    return {
      names:['wjm','zp','ks','and...']
    }
  }
}
</script>