欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Vue手寫一個對話框

 更新時間:2024年04月11日 09:59:21   作者:spriteApe  
相信大家之前都寫過一些組件,尤其是這樣的彈窗組件,這篇文章主要來和大家聊聊如何使用Vue手寫一個對話框,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

寫在前面

相信大家之前都寫過一些組件,尤其是這樣的彈窗組件,沒吃過豬肉還沒見過豬跑嘛 哈哈哈~

有人可能會說,為什么要自己寫,我就用ant-design或者餓了么的。sorry,我要的彈窗UI跟組件庫的相差太遠(yuǎn)了,而且對話框組件通常都掛載在body下,要改樣式的話得一個個去寫全局的樣式,會全局覆蓋掉組件庫的css…… 微調(diào)改樣式就還好。如果組件庫的對話框dom結(jié)構(gòu)跟你想要的差了十萬八千里,那也是佛祖難救……

基本實現(xiàn)

<template>
  <Teleport to="body">
    <div
      class="popDialogMask"
      :style="{ zIndex: props.zIndex }"
      v-show="modalOpen"
      @click="props.maskClosable && (modalOpen = false)"
      v-bind="$attrs"
    >
      <div class="popDialogContent" @click.stop :style="{ width: props.width + 'px' }">
        <slot name="title">
          <div class="title">
            <div class="i-carbon:warning mr-2 color-#FF9A42" />
            {{ props.title }}
          </div>
        </slot>
        <slot name="content">
          <div class="content"></div>
        </slot>
        <slot name="footer">
          <div class="footer">
            <a-button
              type="primary"
              ghost
              @click="handleEdit('cancel')"
              v-if="cancelButtonVisible"
              >{{ props.cancelText }}</a-button
            >
            <a-button type="primary" @click="handleEdit('confirm')" :block="!cancelButtonVisible">{{
              props.okText
            }}</a-button>
          </div>
        </slot>
      </div>
    </div>
  </Teleport>
</template>

<script lang="ts" setup>
import { type IDiaLogProps } from './types'
const modalOpen = defineModel<boolean>('open')
const props = withDefaults(defineProps<IDiaLogProps>(), {
  title: '',
  maskClosable: false,
  cancelButtonVisible: true,
  zIndex: 2000,
  okText: '確定',
  cancelText: '取消',
  width: 640,
})
const emits = defineEmits(['confirm', 'cancel'])
const handleEdit = (type: Parameters<typeof emits>[0]) => {
  modalOpen.value = false
  emits(type)
}
</script>
<style lang="scss" scoped>
.popDialogMask {
  @apply fixed top-0 bottom-0 left-0 right-0  flex justify-center items-center;
  background-color: rgba(0, 0, 0, 0.45);
  .popDialogContent {
    @apply bg-white rounded-3xl  p-12 box-border;
    .title {
      @apply text-3xl flex justify-center items-center font-bold;
    }
    .content {
      @apply h-26;
    }
    .footer {
      @apply flex justify-between;
      :deep(.ant-btn) {
        @apply p-x-22.5 rounded-20 p-y-0 text-3xl;
        height: 80px;
        line-height: 80px;
      }
    }
  }
}
</style>

順便我要講一下vue的defineModel這個語法糖,用起來真香

組件中使用

下面給出一個基本示例

    <pos-dialog
      v-model:open="posDialogVisible"
      title="我是title"
      :cancelButtonVisible="false"
    >
      <template #content>
        <div class="my-13 text-center">content</div>
      </template>
    </pos-dialog>

API方式調(diào)用

下面我們在utils中把組件引入,導(dǎo)出一個工具函數(shù)給我們后續(xù)API方式"食用"

export const showPosDialog = (option: typeof PosDialog.props) => {
  const modalWarp = document.createElement('div')
  const destroy = () => {
    // eslint-disable-next-line no-use-before-define
    modalInstance.unmount()
    //因為用了Teleport 我發(fā)現(xiàn)這里不寫最好
    // document.body.removeChild(modalWarp)
  }
  const modalInstance = createApp(PosDialog, {
    ...option,
    open: true,
    //AOP
    onConfirm() {
      option.onConfirm && option.onConfirm()
      destroy()
    },
    onCancel() {
      option.onCancel && option.onCancel()
      destroy()
    },
  })
  modalInstance.mount(modalWarp)
   //因為用了Teleport 我發(fā)現(xiàn)這里不寫最好
  // document.body.appendChild(modalWarp)
}

使用方法

下面給出一個基本示例

  showPosDialog({
    title: '是否移除該商品?',
    onConfirm() {
      emits('delete')
    },
  })

這樣,我們就實現(xiàn)了一個組件既可以在template中使用,也可以在任何js中使用啦

初始不渲染

不知道大家有沒有注意到,組件庫的對話框在第一次打開之前,是沒有掛載到body節(jié)點下的。上面我們封裝的組件,如果有100個對話框,頁面一開始就會在body下掛載100個節(jié)點,且都是實例化完成后的,增加了性能上的開銷

投石問路

這可咋整,百度也不知道怎么問。一時間沒有好的思路,我就去down一個ant-design-vue的源碼看看。不得不說,這個項目是一層組件套一層,太雞兒復(fù)雜了。功夫不負(fù)有心人,我在components/_util/Portal.tsx文件第69行看到了這么一行代碼

    return () => {
      if (!shouldRender.value) return null;
      if (isSSR) {
        return slots.default?.();
      }
      //沒錯,就是這行!
      return container ? <Teleport to={container} v-slots={slots}></Teleport> : null;
    };

ant-design設(shè)計思路比較復(fù)雜,咱就不過多深究了,反正實現(xiàn)思路是有了。搞個組件包一層。如果是第一次且綁定值為false那就返回一個null

具體實現(xiàn)

import { type IDiaLogProps } from './types'
import Dialog from './Dialog.vue'
export default defineComponent<IDiaLogProps & { open: boolean }>({
  name: 'PosDialog',
  inheritAttrs: false,
  props: Dialog.props,
  setup(props, { attrs, slots }) {
    const isFirstRender = ref(true)
    // 初始值為false的話需要監(jiān)聽第一次打開
    if (!props.open) {
      // 打開過一次dialog 后,將 isFirstRender 設(shè)置為 false
      const unWatch = watch(
        () => props.open,
        (val) => {
          if (val) {
            isFirstRender.value = false
            unWatch()
          }
        }
      )
    } else {
      isFirstRender.value = false
    }

    return () => {
      return isFirstRender.value ? null : <Dialog v-slots={slots} {...props} {...attrs} />
    }
  },
})

干這種活還是用tsx用起來比較順手,寫的時候注意把props、slot、attrs這些透傳下去即可

vNode

其實在API方式調(diào)用時,我們還可以傳vNode給組件。

修改組件

修改組件中需要支持vNode的插槽

        <component :is="props.title" v-if="isVNode(props.title)"></component>
        <slot name="title" v-else>
          <div class="title">
            <div class="i-carbon:warning mr-2 color-#FF9A42" />
            {{ props.title }}
          </div>
        </slot>

使用vNode

  showPosDialog({
   // title: '是否移除該商品?',
    title: <div>vNode:是否移除該商品?</div>,
    onConfirm() {
      emits('delete')
    },
  })

思考

實現(xiàn)過程沒有那么順暢,但也算是填補一部分技術(shù)空白吧。如果大佬有更好的想法,歡迎在評論區(qū)交流呀

別人都用hooks我為什么用工具函數(shù)

反正各有各的看法吧,用hooks可以方便用vue的響應(yīng)式數(shù)據(jù)、生命周期鉤子等等,但是只能在vue組件中去調(diào)用。我的實現(xiàn)沒有用到vue的這些東西,所以就寫成工具函數(shù)了,在哪都可以調(diào)用。

個人覺得,沒有用到vue這些東西,沒必要強制hooks化。

再看vue的hooks使用,實際上就是在構(gòu)建之初實例化一次,后續(xù)的"消費"在于調(diào)用返回的函數(shù)。像我這種API的對話框,就是創(chuàng)建的時候?qū)嵗淮?,關(guān)閉后就銷毀了。沒有復(fù)用一說,也就沒必要寫成hooks了

至于為什么不復(fù)用,如果同時存在兩個API調(diào)起的對話框,你只有一個實例(復(fù)用方案),那無法滿足需求了

總結(jié)

相比于我之前封裝的組件,我覺得對話框?qū)儆诼杂刑厥獾慕M件吧。

  • 得掛載body下防止樣式層級受影響
  • 需要支持API方式調(diào)用
  • 初始不渲染
  • 支持vNode傳參

到此這篇關(guān)于使用Vue手寫一個對話框的文章就介紹到這了,更多相關(guān)Vue對話框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue.js中window.onresize的超詳細(xì)使用方法

    vue.js中window.onresize的超詳細(xì)使用方法

    這篇文章主要給大家介紹了關(guān)于vue.js中window.onresize的超詳細(xì)使用方法,window.onresize 是直接給window的onresize屬性綁定事件,只能有一個,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • vue二次封裝一個高頻可復(fù)用組件的全過程

    vue二次封裝一個高頻可復(fù)用組件的全過程

    在開發(fā)Vue項目我們一般使用第三方UI組件庫進(jìn)行開發(fā),但是這些組件提供的接口并不一定滿足我們的需求,這時我們可以通過對組件庫組件的二次封裝,來滿足我們特殊的需求,這篇文章主要給大家介紹了關(guān)于vue二次封裝一個高頻可復(fù)用組件的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • vue項目部署到Apache服務(wù)器中遇到的問題解決

    vue項目部署到Apache服務(wù)器中遇到的問題解決

    這篇文章主要介紹了vue項目部署到Apache中遇到的問題解決,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • Vue之自定義事件內(nèi)容分發(fā)詳解

    Vue之自定義事件內(nèi)容分發(fā)詳解

    這篇文章主要為大家介紹了Vue的自定義事件內(nèi)容分發(fā),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • 詳解vue中v-model的實現(xiàn)原理

    詳解vue中v-model的實現(xiàn)原理

    v-model可以實現(xiàn)數(shù)據(jù)的雙向綁定,也是vue的最突出的優(yōu)勢,其實 v-model 實際上是一個語法糖,本文將給大家介紹一下vue中v-model的實現(xiàn)原理,文中有相關(guān)的代碼供大家參考,具有一定的參考價值,需要的朋友可以參考下
    2023-12-12
  • vue2.0構(gòu)建單頁應(yīng)用最佳實戰(zhàn)

    vue2.0構(gòu)建單頁應(yīng)用最佳實戰(zhàn)

    這篇文章主要為大家分享了vue2.0構(gòu)建單頁應(yīng)用最佳實戰(zhàn)案例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • vue-class-setup?編寫?class?風(fēng)格組合式API

    vue-class-setup?編寫?class?風(fēng)格組合式API

    這篇文章主要為大家介紹了vue-class-setup?編寫?class?風(fēng)格組合式API,支持Vue2和Vue3,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • vue項目中vant tab改變標(biāo)簽顏色方式

    vue項目中vant tab改變標(biāo)簽顏色方式

    這篇文章主要介紹了vue項目中vant tab改變標(biāo)簽顏色方式,具有很好的參考價值,希望對大家有所幫助。
    2022-04-04
  • Vue狀態(tài)機的開啟與停止操作詳細(xì)講解

    Vue狀態(tài)機的開啟與停止操作詳細(xì)講解

    Vuex是專門為Vuejs應(yīng)用程序設(shè)計的狀態(tài)管理工具,這篇文章主要給大家介紹了關(guān)于Vuex狀態(tài)機快速了解與實例應(yīng)用的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • vue使用axios跨域請求數(shù)據(jù)問題詳解

    vue使用axios跨域請求數(shù)據(jù)問題詳解

    這篇文章主要為大家詳細(xì)介紹了vue使用axios跨域請求數(shù)據(jù)的問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評論