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)])
      }
    },
  }
}
相关推荐
~无忧花开~5 小时前
JavaScript学习笔记(十五):ES6模板字符串使用指南
开发语言·前端·javascript·vue.js·学习·es6·js
泰迪智能科技015 小时前
图书推荐丨Web数据可视化(ECharts 5)(微课版)
前端·信息可视化·echarts
CodeCraft Studio6 小时前
借助Aspose.Email,使用 Python 读取 Outlook MSG 文件
前端·python·outlook·aspose·email·msg·python读取msg文件
家里有只小肥猫7 小时前
react 初体验2
前端·react.js·前端框架
慧慧吖@7 小时前
前端发送请求时,参数的传递格式
前端
L李什么李7 小时前
HTML——使用表格制作简历
前端·javascript·html
未来之窗软件服务7 小时前
万象EXCEL开发(八)excel公式解析与依赖映射 ——东方仙盟金丹期
前端·excel·仙盟创梦ide·东方仙盟·万象excel
linuxxx1107 小时前
ajax() 回调函数参数详解
前端·ajax·okhttp
王嘉俊9257 小时前
ThinkPHP 入门:快速构建 PHP Web 应用的强大框架
开发语言·前端·后端·php·框架·thinkphp
我有一棵树8 小时前
html 滚动条相关开发经验总结
前端·javascript·html