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)])
      }
    },
  }
}
相关推荐
小雨青年2 分钟前
智能交互新范式:拒绝“黑盒”,带你用 MateChat 与 DSL 构建“高可靠”的 NL2UI 引擎
前端·ai·华为云
anyup5 分钟前
🔥牛逼!3分钟生成 5 套主题,还能一键切换暗黑模式!
前端·前端框架·uni-app
进击的明明5 分钟前
深入讨论前端开发中的跨域问题🤔
前端
正在走向自律9 分钟前
企业微信消息推送全链路实战:Java后端与Vue前端集成指南
前端·vue.js·企业微信·企业微信消息推送·官方企业微信
_一两风9 分钟前
《从一道“诡异”输出题,彻底搞懂 JavaScript 的作用域与执行上下文》
前端·ecmascript 6
lcc18713 分钟前
Vue3 CompositionAPI的优势
前端·vue.js
五号厂房18 分钟前
聊一聊前端下载文件N种方式
前端
code_Bo21 分钟前
使用micro-app 多层嵌套的问题
前端·javascript·架构
小灰22 分钟前
VS Code 插件 Webview 热更新配置
前端·javascript
进击的明明27 分钟前
前端监控与前端兜底:那些我们平常没注意,但真正决定用户体验的“小机关”
前端·面试