• Vue3你需要知道的组件化知识点


    组件命名

    官方建议我们使用大驼峰命名法注册组件,因为:

    1. 驼峰命名是合法的JS标识符,导入、注册组件会更简单,IDE会自动完成。
    2. 使Vue组件比原生HTML元素更醒目。

    例如,使用组件Pascalcase.vue

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

    属性定义

    使用更细节的方式定义属性:

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

    事件定义

    自定义事件的名称会被自动做转换,我们通常使用驼峰做事件名,但监听时需要转换为肉串方式。

    例如:

    
    
    
    • 1
    • 2
    
    
    • 1

    script setup中定义

    
    
    • 1
    • 2
    • 3
    • 4

    透传特性

    vue3中,那些没有明确在组件props和emits中声明的特性或事件监听器称为透传特性,以前叫非属性特性。比如class,styleid特性。当组件只有单根时,透传特性自动被添加到根元素上作为其特性。例如:

    
    
    • 1
    
    
    • 1

    如果不想自动继承特性,可以使用inheritAttrs: false禁止

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

    Vue3中插槽的变化是移除scopeSlots,只需要访问slots对象,且包括default插槽都是函数形式。

    访问透传特性

    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    插槽

    如果要传递模板内容给子组件,我们使用插槽。

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

    提供/注入 provide/inject

    隔代传参时,使用provide/inject这组API。

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    import { inject } from 'vue'
    
    export default {
      setup() {
        // 后代注入数据
        inject(/* key */ 'message', /* value */ 'hello!')
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Composables

    利用Composition API封装的可重用状态逻辑称为composables

    约定composables函数命名时加上use前缀,例如:

    // mouse.js
    import { ref, onMounted, onUnmounted } from 'vue'
    
    // by convention, composable function names start with "use"
    export function useMouse() {
      // state encapsulated and managed by the composable
      const x = ref(0)
      const y = ref(0)
    
      // a composable can update its managed state over time.
      function update(event) {
        x.value = event.pageX
        y.value = event.pageY
      }
    
      // a composable can also hook into its owner component's
      // lifecycle to setup and teardown side effects.
      onMounted(() => window.addEventListener('mousemove', update))
      onUnmounted(() => window.removeEventListener('mousemove', update))
    
      // expose managed state as return value
      return { x, y }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    传入refs参数代替原始值

    import { unref } from 'vue'
    
    function useFeature(maybeRef) {
      // if maybeRef is indeed a ref, its .value will be returned
      // otherwise, maybeRef is returned as-is
      const value = unref(maybeRef)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    总是返回包含refs的对象

    // x and y are refs
    const { x, y } = useMouse()
    
    • 1
    • 2

    组件通信

    组件通信常⽤⽅式,vue3中有很多变化:

    • props:父子通信,传入一个属性
    {
      props: { msg: String }
    }
    
    
    • 1
    • 2
    • 3
    • 4

    除了props选项,vue3.2还出了script setup的新写法

    const props = defineProps({
      model: { type: Object, required: true }
    });
    props.model
    
    • 1
    • 2
    • 3
    • 4
    • $emit:

    现在只剩下派发事件的emit方法

    this.$emit('add', good)
    
    • 1

    vue3.2还出了script setup的新写法

    const emit = defineEmits(['update:model-value', 'validate'])
    const emit = defineEmits<{
      (e: "update:model-value", value: string): void;
      (e: "validate"): void;
    }>();
    emit("update:model-value", inp.value);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    o n , on, ononce, $off被移除了!

    上述3个⽅法被认为不应该由vue提供,因此被移除了,可以使⽤其他库实现等效功能。

    import mitt from 'mitt'
    
    const emitter = mitt()
    
    // 发送事件
    emitter.emit('foo', 'foooooooo')
    
    // 监听事件
    emitter.on('foo', msg => console.log(msg))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • event bus

    vue2时代我们常常使用一个vue实例来做事件总线,现在不行了:

    所以我们就使用上面的mitt方案来代替就好了!

    // vue2时代,现在因为没有$on不行了
    Vue.prototype.$bus = new Vue()
    
    // 组件里面
    this.$bus.$emit('xxx')
    
    // 其他组件
    this.$bus.$on('xxx', () => {})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • vuex/pinia

    vuex 4.x中的composition api写法:

    const store = useStore()
    store.commit('add')
    store.dispatch('add')
    
    • 1
    • 2
    • 3
    • parent/root

    兄弟组件之间通信可通过共同祖辈搭桥。

    // brother1
    this.$parent.$on('foo', handle)
    // brother2
    this.$parent.$emit('foo')
    
    • 1
    • 2
    • 3
    • 4
    • $children

    vue3中移除了该选项,官方建议我们访问子组件时使用$refs

    • $refs

    获取指定元素或组件

    // parent
    
    mounted() {
      this.$refs.hw.xx = 'xxx'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • provide/inject

    能够实现祖先和后代之间传值

    在composition中有对应的api

    // ancestor
    provide() {
      return {foo: 'foo'} 
    }
    // descendant
    inject: ['foo']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    import {provide, inject} from vue
    // 提供数据
    provide(key, value)
    // 注入数据
    inject(key)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • $attrs:

    a t t r s 会包含那些没有声明的组件特性, v u e 3 中移除了 attrs会包含那些没有声明的组件特性,vue3中移除了 attrs会包含那些没有声明的组件特性,vue3中移除了listeners,只剩下$attrs:

    // child:并未在props中声明foo
    

    {{$attrs.foo}}

    // parent
    • 1
    • 2
    • 3
    • 4

    通过 v-bind=“$attrs” 透传到内部组件——在创建⾼级别的组件时⾮常有⽤:

    // 给Grandson隔代传值,parent.vue
    
    
    // Child做展开
    
    
    // Grandson使⽤
    
    {{msg}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    插槽

    插槽语法是Vue 实现的内容分发 API,⽤于复合组件开发。该技术在通⽤组件库开发中有⼤量应⽤。

    匿名插槽

    slot称为匿名插槽,作为占位符存在,将来被替换为传入内容。

    // comp1
    
    // parent hello
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    具名插槽

    slot加上name就称为具名插槽,可以将内容分发到⼦组件指定位置

    // comp2
    
    // parent
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    作⽤域插槽

    分发内容要⽤到⼦组件中的数据

    // comp3
    
    // parent
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Vue3中组件相关API变化总结

    global-api改为实例⽅法

    全局静态⽅法引发⼀些问题,vue3将global-api改为app实例⽅法

    // vue2中
    // Vue.component()
    
    // vue3中
    const app = createApp({})
     .component('comp', {template: '
    i am comp
    '}) .mount('#app')
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    移除.sync,统⼀为v-model

    以前.sync和v-model功能有重叠,容易混淆,vue3做了统⼀。

    • 1
    • 2
    • 3
    • 4
    • 5
    app.component('comp', {
      props: {
        modelValue
      },
      template: `
        
    i am comp, {{modelValue}}
    `, props: ['modelValue'], })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    渲染函数api修改

    不再传⼊h函数,需要我们⼿动导⼊;拍平的props结构。scopedSlots删掉了,统⼀到slots

    import {h} from 'vue'
    
    export default {
      render() {
        const emit = this.$emit
        const onclick = this.onclick
        return h('div', [
          h('div', { onClick(){ emit('update:modelValue', 'new value')} }, 
            `i am comp, ${this.modelValue}`),
           h('button', { onClick(){ onclick() }}, 'buy it!')
        ])
      },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    组件emits选项

    该选项⽤于标注⾃定义事件及其校验等。

    createApp({}).component("comp", {
      template: `...`,
      // emits标明组件对外事件
      emits: ['buy', '...']
      // 还能对事件进行校验
      emits: {
        'update:modelValue': null, // 不做校验
        buy(p) { // 校验buy事件
          if (p === 'nothing') {
            console.warn('参数⾮法');
            return false
          } else {
            return true
          }
        }
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    计算机毕业设计(附源码)python中小型医院综合管理系统
    《算法竞赛进阶指南》差分约束 区间
    模拟电路 第二章(三极管及其放大电路)【下】
    mysql的sum求和函数求和性能优化
    还在烦恼怎样压缩PDF吗?看看这3个实用的方法吧
    基于QT和C++实现的停车场管理系统
    【Java 进阶篇】JQuery 遍历 —— 无尽可能性的 `each` 之旅
    我赢助手之引流篇:短视频私域、自有鱼塘背后的底层逻辑是什么?
    【已解决】msvcp140.dll丢失怎样修复?msvcp140.dll重新安装的解决方法
    Flink学习17:算子介绍flatMap
  • 原文地址:https://blog.csdn.net/weixin_59816940/article/details/127567054