Vue开发尝试一下

1. provide传多个函数/属性

常规

js 复制代码
    // parent.vue
    const key = Symbol('sonContext')
    provide(key,{
        fn1:()=>{},
        fn2:()=>{}
    })
    // son.vue
    const context = inject(key)
    context?.fn1()

进阶

js 复制代码
// 封装成hook,调用方只关注传值即可,key在hook维护与组件解耦
import { inject, provide } from 'vue'
function useCreateProvide(key){
    // key也可以不传写死,每次调用都是最新的Symbol
    // const key = Symbol('provideKey')
    return [
        function useProvide(value){
            provide(key,value)
        },
        function useInject(defaultValue){
            return inject(key,defaultValue)
        }
    ]
}
const [useUserProvide,useUserInject] = createProvideState(Symbol('user'))
const [useSonProvide,useSonInject] = createProvideState(Symbol('son'))
export { useUserProvide, useUserInject, useSonProvide, useSonInject }

2.异步组件

  • 使用场景
js 复制代码
// 场景  组件从远程js获取 需要二次处理
import { h } from 'vue'
const items = [
    {type:'input',key:'name'},
    {url:'https://cdn.jsdelivr.net/npm/element-plus@2.10.4/es/components/affix/index.mjs'}
]
const Comp = {
  setup(_, { attrs, slots }) {
    const component = () =>
      defineAsyncComponent(() => {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve({
              render() {
                return h('div', 'hello world')
              },
            })
          }, 1000)
        })
      })
    return h(component, attrs, slots)
  },
}
  • 简单实现一下低代码时远程获取组件
js 复制代码
const Comp = {
  props:['item'],
  setup(props){
    const component = ref(()=>return h('div',''))
    const url = props.item.url || 'https://unpkg.com/ant-design-vue/lib/index.js'
    const name = props.item.name || 'AButton'
    function loadScript(){
      import(url).then(module=>{
        const Comp = module[name]
        component.value = Comp
      })
    }
    loadScript()
    return h(component.value)
  }
}
  • 有了上面的基础来实现defineAsyncComponent
js 复制代码
//loader是个函数返回promise resove一个组件
function defineAsyncCompont(loader) {
  return {
    setup() {
      const componet = ref(() => h('span'))
        loader().then((res) => {
         // 处理一下 defineAsyncCompont(import('./Button.js'))
          if (res && res[Symbol.toStringTag] === 'module') {
            res = res.default
          }
          componet.value = res
        })
      return () => {
        return h(componet.value)
      }
    },
  }
}
  • 进阶(defineAsyncComponent接收对象可定义loader和loading error组件)
js 复制代码
import { h } from 'vue'
const Comp = {
  setup(_, { attrs, slots }) {
    const component = () =>
      defineAsyncComponent({
        loader: () => import('./ceshi.vue'),
        loadingComponent: {
            render(){
                return h('div','loading')
            }
        },
        errorComponent: () => import('./error.vue'),
      })
    return h(component, attrs, slots)
  },
}
  • 终极版实现异步组件
js 复制代码
export function defineAsyncComponent(options) {
  if (typeof options === 'function') {
    options = {
      loader: options,
    }
  }

  // 占位符组件
  const defaultComponent = () => h('span')

  const {
    loader,
    loadingComponent = defaultComponent,
    errorComponent = defaultComponent,
    timeout,
  } = options

  return {
    setup(_, { attrs, slots }) {
      const component = shallowRef(loadingComponent)

      function loadComponent() {
        return new Promise((resolve, reject) => {
          /**
           * 到点了,还没完成,我就调用 reject
           */
          if (timeout && timeout > 0) {
            setTimeout(() => {
              reject('超时了')
            }, timeout)
          }

          loader().then(resolve, reject)
        })
      }

      /**
       * loader 函数返回一个 Promise
       * 但是这个 Promise 我们不能控制它的成功和拒绝
       */
      loadComponent()
        .then((res) => {
          if (res && res[Symbol.toStringTag] === 'Module') {
            res = res.default
          }
          /**
           * 1000 ms 会进来
           */

          component.value = res
        })
        .catch(() => {
          // 组件加载失败了,改为 defaultComponent
          component.value = errorComponent
        })

      return () => {
        return h('div', [h(component.value, attrs, slots)])
      }
    },
  }
}
相关推荐
奇舞精选16 小时前
超越Siri的耳朵:ASR与Whisper零代码部署实战指南
前端·人工智能·aigc
奇舞精选16 小时前
Nano Banana 如何为前端注入 AI 控制力
前端·aigc
一支鱼16 小时前
基于 Node.js 的短视频制作神器 ——FFCreator
前端·node.js·音视频开发
DT——17 小时前
前端登录鉴权详解
前端·javascript
李姆斯17 小时前
复盘上瘾症:到底什么时候该“复盘”,什么时候不需要“复盘”
前端·后端·团队管理
whysqwhw17 小时前
Kuikly 原生 API 扩展机制对比总结
前端
亮子AI17 小时前
【Tailwind, Daisyui】响应式表格 responsive table
前端
LJC_Superman18 小时前
Web与Nginx网站服务
运维·服务器·前端·网络·数据库·nginx·vim
星秋Eliot18 小时前
Flutter的三棵树
前端·flutter
正义的大古18 小时前
OpenLayers常用控件 -- 章节六:全屏控件教程
前端·javascript·html·openlayers