• 08 【Props 组件事件】


    15.Props

    15.1 Props 声明#

    Props 是一种特别的 attributes,你可以在组件上声明注册。要传递给子组件内容,我们必须在组件的 props 列表上声明它。

    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    defineProps 是一个仅

    • 1
    • 2
    • 3

    这声明了一个组件可能触发的所有事件,还可以对事件的参数进行验证。同时,这还可以让 Vue 避免将它们作为原生事件监听器隐式地应用于子组件的根元素。

    defineProps 类似,defineEmits 仅可用于

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    defineEmits()不能在子函数中使用。如上所示,它必须直接放置在

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果你正在搭配 TypeScript 使用

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    现在 v-model 也可以在这个组件上正常工作了:

    
    
    • 1

    在演练场中尝试一下

    v-model 的参数#

    默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件。我们可以通过给 v-model 指定一个参数来更改这些名字:

    
    
    • 1

    在这个例子中,子组件应声明一个 title prop,并通过触发 update:title 事件更新父组件值:

    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在演练场中尝试一下

    16.6 关于组件使用原生事件

    这是我目前想到的,如果有错误,请指出

    Vue3移除v-on.native修饰符,那如何在组件上触发原生事件呢?

    其实可以利用属性继承,详细可以看17.1 Attributes 继承

    注意要写根标签,因为这个事件只会继承在根标签因为Vue3不强制写根标签,所以会出现多个标签,这时这个事件找不到根标签会发出警告,解决的方法在Attributes 继承里面说了

    父组件App.vue

    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    子组件Son.vue

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20220809130712485

    16.7 vue3中事件总线

    16.7.1 插件

    1.在vue3中,创建方法改成了createApp({}),prototype属性也被取消了,因此无法使用之前Vue.prototype.$bus = new Vue()的方式使用事务总线。

    2.且在vue3中移除了 o n , on, on,off方法,因此官方推荐:事件总线模式可以被替换为使用外部的、实现了事件触发器接口的库,例如 mitt 或 tiny-emitter。

    3.首先安装mitt:npm install --save mitt

    4.在代码中使用:

    import mitt from "mitt"
    import {createApp} from "vue"
     
    const app = createApp(App)//正常配置
    //挂载事务总线
    app.config.globalProperties.$bus = mitt()
     
    //在组件A中使用事务总线触发某个动作
    import {getCurrentInstance } from 'vue';
    const instance = getCurrentInstance();
    function send() {
      instance.proxy.$bus.emit('receive', '你是一个瓜皮');
    }
     
    //在组件B中监听动作的发生
    import { getCurrentInstance } from 'vue';
    let data = ref('');
    
    const instance = getCurrentInstance();
    instance.proxy.$bus.on('receive', str => {
      console.log('来数据了');
      data.value = str;
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    对于ts文件的写法

    import { createApp } from 'vue'
    import App from './App.vue'
    import mitt from 'mitt'
     
    const Mitt = mitt()
     
    //TypeScript注册
    // 由于必须要拓展ComponentCustomProperties类型才能获得类型提示
    declare module "vue" {
        export interface ComponentCustomProperties {
            $bus: typeof Mitt
        }
    }
     
    const app = createApp(App)
     
    //Vue3挂载全局API
    app.config.globalProperties.$Bus = Mit
     
    app.mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    16.7.2 手写

    Bus.ts

    import * as Console from 'console'
    
    
    type BusClass = {
      emit: (name: string) => void,
      on: (name: string, callback: Function) => void
    }
    
    type CallbackName = string | number | symbol
    
    type List = {
      [key: CallbackName]: Array<Function>
    }
    
    class Bus implements BusClass {
      list: List
    
      constructor() {
        this.list = {}
      }
    
      emit(name: string, ...args: Array<any>) {
        let callbacks: Array<Function> | undefined = this.list[name]
        if (callbacks === undefined) {
          console.warn(`event "${name}" is not bound`)
          return
        }
        callbacks.forEach(callback => {
          console.log('emit', this)
          callback.apply(this, args)  // this 为 Bus.ts 导出的实例, on方法如果使用ArrowFunction, 则无法使用this
        })
      }
    
      on(name: string, callback: Function) {
        let callbacks: Array<Function> = this.list[name] || []
        callbacks.push(callback)
        this.list[name] = callbacks
      }
    }
    
    export default new Bus < BusParams >()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    挂载到全局Vue config
    或者单独的页面引入 import Bus from ‘bus.ts’
    Bus.emit 触发,Bus.on监听

    image-20220810185533253

    main.ts

    import { createApp } from 'vue'
    import App from './App.vue'
    import Bus from "./utils/Bus"
    const app = createApp(App);
    app.config.globalProperties.$bus = Bus;
    app.mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用方法和插件一模一样

  • 相关阅读:
    『干货』WebStorm代码模板配置大全
    冰冰学习笔记:string类的简单模拟
    Dubbo基本操作
    离散数学-万字课堂笔记-期末考试-考研复习-北航离散数学1
    vue3-admin商品管理后台项目(后台主控台开发与交互)
    NFC隐藏功能大公开:乘车刷门禁,NFC实用无风险
    c语言每日一练(15)
    软考 系统架构设计师 简明教程 | 软件开发方法
    上门预约服务类的App功能详解
    蚂蚁集团数字科技六大新品发布,以数助实赋能产业数字化
  • 原文地址:https://blog.csdn.net/DSelegent/article/details/126237707