91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何用Vue實現Dialog封裝

發布時間:2022-10-12 15:21:41 來源:億速云 閱讀:214 作者:iii 欄目:web開發

這篇文章主要講解了“如何用Vue實現Dialog封裝”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何用Vue實現Dialog封裝”吧!

在寫業務的時候很常見的一個場景就是需要在不同的頁面調用同一個表單,常用的交互就是把表單以彈窗的形式展示,但是在每個頁面又重復的引入表單組件有時候又很麻煩

如何用Vue實現Dialog封裝

解決方案有兩個:

  1. 在根組件里面引入動態組件,在業務里面通過this.$root.openDialog(name, props)去控制動態組件的展示形式

  2. 封裝成插件的形式去調用,比如this.$dialog("EditDialog.vue", props)

當然了,業務 Dialog 組件要有一套規范,props 接收一個 onOk、onCancel 回調,data 里面定義一個 visible 屬性

<template>
  <el-dialog :title="title" :visible.sync="visible" append-to-body>
    <!-- 業務代碼 -->
  </el-dialog>
</template>

<script>
export default {
  props: ["onOk", "其他業務需要的屬性"],
  data() {
    return {
      visible: false
    }
  }
}
</script>

Vue2 寫法

在 Vue2 里面我個人感覺寫成插件是比較好用的,實現如下,使用混入做了一些操作,和業務進行解耦

有點不太好的地方是組件是動態插入的,Vue devtools 要刷新下才能看到組件

const mixin = {
  mounted() {
    document.body.appendChild(this.$el)
    this.visible = true
  },
  watch: {
    visible(value) {
      // 動畫結束后銷毀實例
      if (value === false) {
        setTimeout(() => {
          this.$destroy()
          if (this.$el && this.$el.parentNode) {
            this.$el.parentNode.removeChild(this.$el)
          }
        }, 400)
      }
    }
  }
}

export default {
  install(Vue, options) {
    Vue.prototype.$dialog = (name, props) => {
      // 相對于該插件的位置,靜態編譯期間會檢查的
      import("../components/dialogs/" + name)
        .then(module => {
          const component = module.default
          const mixins = component.mixins || []
          mixins.push(mixin) // 實現自動打開,動態了混入生命周期函數和銷毀操作
          component.mixins = mixins
          return Vue.extend(component)
        })
        .then(Dialog => {
          const dialog = new Dialog({
            propsData: props || {}
          })
          dialog.$mount()
        })
    }
  }
}

調用方式如下,注意 onOk 回調的 this 指向,使用箭頭函數直接就避免了 ?

this.$dialog("GroupEdit.vue", {
  type: "edit",
  group: {},
  onOk: () => {
    this.freshList()
  }
})

Vue3 插件版寫法

很糟糕的是,由于 Vue3 的升級Vue.extend沒有了,$mount也沒有了,組件只能在應用里面去渲染

每個應用之間的數據是隔離的,所以插件什么的都要重新引入。同時如果要交互交互的話也比較麻煩,引入同一個 vuex 實例應該可以,但是沒怎試

為了低耦合只能去新建一個應用去掛載渲染

如何用Vue實現Dialog封裝

import { createApp, defineComponent } from "vue"
import ElementPlus from "element-plus"

const mixin = {
  mounted() {
    document.body.appendChild(this.$el)
    this.visible = true
  },
  watch: {
    visible(value) {
      // 動畫結束后銷毀實例
      if (value === false) {
        setTimeout(() => {
          this.$.appContext.app.unmount()
        }, 400)
      }
    }
  }
}

export default {
  install(app) {
    app.config.globalProperties.$dialog = (name, props) => {
      import("../components/dialogs/" + name)
        .then(module => {
          const component = module.default
          let mixins = component.mixins || []
          mixins.push(mixin)
          component.mixins = mixins

          return defineComponent(component)
        })
        .then(Dialog => {
          const app = createApp(Dialog, props || {})
          app.use(ElementPlus)
          app.mount(document.createElement("div"))
        })
    }
  }
}

Vue3 動態組件寫法

在 Vue3 里面,插件版的寫法同樣達到了要求,但是完全是一個新引應用了,如果在業務里訪問this.$root,vuex,router還是有點麻煩的

所以 Vue3 里面還是動態組件的寫法比較好

在根組件引入動態 component,定義一些控制變量

<template>
  <router-view></router-view>
  <component :is="currentDialog" v-bind="currentDialogProps" />
</template>

<script>
export default {
  data() {
    return {
      currentDialog: null,
      currentDialogProps: null
    }
  }
}
</script>

調用的的話this.$root.$dialog(),看起來太難看,其實還是可以手動模擬插件的效果的

const app = createApp(App)
const vm = app.mount("#app")

initDialog(app, vm)

function initDialog(app, vm) {
  const mixin = {
    mounted() {
      this.visible = true
    },
    watch: {
      visible(value) {
        // 動畫結束后銷毀實例
        if (value === false) {
          setTimeout(() => {
            this.$root.currentDialog = null
            this.$root.currentDialogProps = {}
          }, 400)
        }
      }
    }
  }

  app.config.globalProperties.$dialog = (name, props) => {
    import("./components/dialogs/" + name).then(module => {
      const component = module.default
      let mixins = component.mixins || []
      mixins.push(mixin)
      component.mixins = mixins
      // 不需要 defineComponent(component)
      vm.currentDialog = markRaw(component)
      vm.currentDialogProps = markRaw(props || {})
    })
  }
}

一些比較 hack 的寫法

vue3 組件實例獲取應用實例

vm.$.appContext.app == app

vue3 應用實例獲取組件實例,注意_instance 僅在 dev 環境能訪問到

app._instance.proxy == vm
app._instance.root.proxy == vm
app._instance.ctx.$root == vm

騷操作還是有的,但是最好不要用

const app = createApp(App)
const vm = app.mount("#app")

if (process.env.NODE_ENV === "production") {
  app._instance = {
    proxy: vm,
    root: {
      proxy: vm
    },
    ctx: {
      $root: vm
    }
  }
}

感謝各位的閱讀,以上就是“如何用Vue實現Dialog封裝”的內容了,經過本文的學習后,相信大家對如何用Vue實現Dialog封裝這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

深泽县| 双鸭山市| 吴川市| 酉阳| 卓尼县| 永和县| 固镇县| 卓资县| 锦州市| 唐海县| 新田县| 应城市| 荃湾区| 万盛区| 卫辉市| 塔城市| 上杭县| 昭觉县| 额尔古纳市| 潮州市| 沙雅县| 定襄县| 朝阳市| 三门峡市| 镇远县| 荆门市| 寿光市| 金昌市| 乌拉特后旗| 诏安县| 山东省| 新丰县| 临猗县| 拉孜县| 商丘市| 同江市| 搜索| 深水埗区| 东方市| 宁城县| 郧西县|