最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Teleport实现Modal组件

    正文概述 掘金(小蝉儿)   2021-05-30   625

    1.认识Teleport

    vue3新增特性Teleport

    像我们如果写Modal组件、Message组件、Loading组件这种全局式组件,没有Teleport的话,将它们引入一个.vue文件中,则他们的HTML结构会被添加到组件模板中,这是不够完美的。

    • 没有Teleport

    Teleport实现Modal组件

    • 有Teleport

    Teleport实现Modal组件

    下面就实战介绍一下如何用Teleport开发Modal组件

    2.Teleport的基本用法

    Teleport的写法十分简单,只需要用<Teleport></Teleport>将内容包裹,并用to指定将HTML挂到哪个父节点下,就可以啦。

    <teleport to="#modal">
    内容
    </teleport>
    

    3.第一步优化

    如果我们在代码中将Teleport要挂载的DOM写死,那么每创建一个全局式组件,就需要有一个DOM节点,会越来越多,并且一直存在,这样的写法不是很优雅。比较好的解决方案就是:

    • 在创建组件的时候,动态创建一个dom节点document.createElement()
    • 并添加到body中,document.body.appendChild()
    • 在组件卸载的时候销毁这个dom document.body.removeChild()
    setup(){
      const node = document.createElement('div')
      node.id = 'modal'
      document.body.appendChild(node)
      onUnmounted(() => {
        document.body.removeChild(node)
      })
    }
    

    4.第二步优化

    如果我们后续还要添加Message组件,Loading组件等功能,同样要用到Teleport,在每一个组件内部都写这么一段代码,实在有点冗余,vue3使我们能够很方便的将逻辑功能提取出来,从而达到逻辑复用的目的。

    我们在src-hooks文件夹下创建useDOMCreate.ts文件,来封装这一块逻辑

    // hooks/useDOMCreate.ts
    import { onUnmounted } from 'vue'
    
    function useDOMCreate(nodeId:string):void {
      const node = document.createElement('div')
      node.id = nodeId
      document.body.appendChild(node)
      onUnmounted(() => {
        document.body.removeChild(node)
      })
    }
    export default useDOMCreate
    
    

    使用:

    import useDOMCreate from '../hooks/useDOMCreate'
    setup(props, ctx) {
        useDOMCreate('modal')
    }
    

    5.实现Modal组件

    具体封装Modal组件的细节这里就不讲啦,也没有什么复杂的逻辑。直接上代码。

    //Modal.vue
    <template>
      <teleport to="#modal">
        <div class="modal d-block" tabindex="-1" v-if="isVisible">
          <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-header">
                <h5 class="modal-title">{{title}}</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                  <span aria-hidden="true" @click="onClose">&times;</span>
                </button>
              </div>
              <div class="modal-body">
                <slot></slot>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal"  @click="onClose">取消</button>
                <button type="button" class="btn btn-primary"  @click="onConfirm">确定</button>
              </div>
            </div>
          </div>
        </div>
      </teleport>
    </template>
    <script lang="ts">
    import { defineComponent } from 'vue'
    import useDOMCreate from '../hooks/useDOMCreate'
    export default defineComponent({
      name: 'Modal',
      emits: ['model-close', 'model-confirm'],
      props: {
        title: {
          type: String,
          default: ''
        },
        isVisible: {
          type: Boolean,
          default: false
        }
      },
      setup(props, ctx) {
        useDOMCreate('modal')
        const onClose = () => {
          ctx.emit('model-close')
        }
        const onConfirm = () => {
          ctx.emit('model-confirm')
        }
        return {
          onClose,
          onConfirm
        }
      }
    })
    </script>
    

    使用示例

    <template>
      <div class="post-detail-page">
        <button type="button" class="btn btn-danger" @click="handleDelete">删除</button>
        <modal title='是否确认删除?' :isVisible="modalVisible" @model-close="hanldeModalClose" @model-confirm="handleModalConfim">
          <p>确认要删除这篇文章吗?</p>
        </modal>
      </div>
    </template>
    <script lang="ts">
    import { defineComponent, ref } from 'vue'
    import Modal from '../components/Modal.vue'
    
    export default defineComponent({
      name: 'post-detail',
      components: { Modal },
      setup() {
        const modalVisible = ref(false)
        const handleDelete = () => {
          modalVisible.value = true
        }
        const hanldeModalClose = () => {
          modalVisible.value = false
        }
        const handleModalConfim = () => {
          modalVisible.value = false
          ...
         / /后续逻辑处理
        }
        return {
          hanldeModalClose,
          handleModalConfim,
          handleDelete,
          modalVisible
        }
      }
    })
    </script>
    

    6.git地址

    后续添加


    下载网 » Teleport实现Modal组件

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元