zoukankan      html  css  js  c++  java
  • vue3如何编写挂载DOM的插件

    文章来源:https://www.cnblogs.com/flicat/p/15062543.html

    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 也正确的解析出来了

     

  • 相关阅读:
    王颖奇 201771010129《面向对象程序设计(java)》第七周学习总结
    王颖奇 201771010129《面向对象程序设计(java)》第六周学习总结
    王颖奇 201771010129《面向对象程序设计(java)》第四周学习总结
    王颖奇 201771010129 第三周 Java基本程序设计总结
    《三带一队》【Alpha】Scrum meeting 3
    《三带一队》【Alpha】Scrum meeting 2
    《三带一队》【Alpha】Scrum meeting 1
    三带一队 实验八 团队作业4:团队项目需求建模与系统设计
    三带一队 实验七 团队作业3:团队项目需求分析与原型设计
    三带一队 实验六团队作业2:麋鹿寻途
  • 原文地址:https://www.cnblogs.com/flicat/p/15062543.html
Copyright © 2011-2022 走看看