• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

关于vue3编写挂载DOM的插件问题

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

vue3 跟 vue2 相比,多了一个 app 的概念,vue3 项目的创建也变成了

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'

const app = createApp(App)
app.use(ElementPlus)   // 使用饿了么框架
app.mount('#app')

所以 Vue.extend 也没有了。

vue2创建一个插件:

export default function install (Vue) {
  let app = Vue.extend({
    render (h) {
      return h('div', {
        style: {
          display: this.isShow ? 'flex' : 'none'
        }
      })
    }
  })

  let appDom = new app({
    el: document.createElement('div'),
    data: function () {
      return {
        isShow: false
      }
    }
  })

  function show () {
    appDom.isShow = true
  }

  function hide () {
    appDom.isShow = false
  }
  Vue.prototype.$show = show
  Vue.prototype.$hide = hide
  document.body.appendChild(appDom.$el)
}

vue3创建一个插件:

import { createApp, h } from 'vue'

export default function install (App) {
  let app = createApp({
    data() {
      return {
        isShow: false,
      }
    },
    render() {
      return h('div', {
        style: {
          display: this.isShow ? 'flex' : 'none'
        }
      })
    }
  })
  
  const vNodeDom = document.createElement('div')
  document.body.appendChild(vNodeDom)
  const vm = app.mount(vNodeDom)

  App.config.globalProperties.$show = function () {
    vm.isShow = true
  }

  App.config.globalProperties.$hide = function () {
    vm.isShow = false
  }
}

对比可以发现, vue3 的 DOM挂载方式是新创建一个 app 然后调用 mount() 方法插入到页面中。

全局方法的挂载方式也从 vue2 的 Vue.prototype 到 vue3 的 App.config.globalProperties。

除此之外,vue3 的插件如果用 createApp 来创建新的DOM结构插入到页面的话,与 main.js 中创建的 app 是隔绝开来的,这意味着 main.js 中 use 的组件和公共方法在 这个插件中无法使用。

// myCom.vue
<template>
  <el-button>按钮</el-button>
</template>


// myCom.js
import { createApp, h } from 'vue'
import myCom from './myCom.vue'
export default function install (App) {
  let app = createApp({
    data() {
      return {
        isShow: false
      }
    },
    render() {
      return h(myCom)
    }
  })

  const vNodeDom = document.createElement('div')
  document.body.appendChild(vNodeDom)
  app.mount(vNodeDom)
}

上面的例子中,el-button 是无法正常显示的,控制台会报错:

[Vue warn]: Failed to resolve component: el-button

 所以,如果既想要新建DOM,又要使用main.js全局注册的组件和方法,那就不能用 createApp,

 在请教了 vue3 的开发大佬后,有了以下方案:(issues

import { render, h } from 'vue'
import myCom from './myCom.vue'

export default function install (App) {
  let vNode = h({
    data() {
      return {
        isShow: false,
      }
    },
    render() {
      return h(myCom)
    }
  })

  const vNodeDom = document.createElement('div')
  document.body.appendChild(vNodeDom)
  vNode.appContext = App._context
  render(vNode, vNodeDom)

  App.config.globalProperties.$show = function () {
    vNode.component.proxy.isShow = true
  }

  App.config.globalProperties.$hide = function () {
    vNode.component.proxy.isShow = false
  }
}

 这次没有创建新的 app,而是通过给 vNode 复制原来 app 的 context,从而达到组件和公共方法共用,

 新创建的插件属性和方法通过 vNode.component.proxy 来访问。

el-button 也正确的解析出来了

到此这篇关于vue3如何编写挂载DOM的插件的文章就介绍到这了,更多相关vue挂载dom插件内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界!


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
详解React中组件之间通信的方式发布时间:2022-02-05
下一篇:
Vue3.0 自己实现放大镜效果案例讲解发布时间:2022-02-05
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap