16.0 vue3 Teleport---自定义dialog组件

上一篇:

15.0 vue3 provide&inject跨组件通信方式_十一月的萧邦-CSDN博客上一篇:14.0 vue3 customRef的使用_十一月的萧邦-CSDN博客上一篇:vue3 toRaw&markRawhttps://blog.csdn.net/qq_42543244/article/details/122793302本篇记录vue3的customRef,customRef是vue3的一大亮点,custom的意思大家都懂,自定义的意思,一旦出现自定义,那么就代表我们可以做很多基于自己的需求的操作,vue3的官方文档的关于这块的示例其实已经蛮不错了,看代码需求是这样,我们需https://blog.csdn.net/qq_42543244/article/details/122869521本篇记录vue3中新标签 Teleport标签,并且来封装一个dialog组件,最后呈现效果:

dialog组件内将会有之前记录学习的知识内容,props传值,slot的使用,refs的调用方式以及Teleport标签等等

 文件目录:

 App.vue

<template>
  <div class="grand">
    <h1>我是app</h1>
    <child></child>
  </div>
</template>

<script>
import Child from "@/components/Child.vue";

export default {
  name: "App",
  components: {
    Child,
  },
  /*
    Fragment:
        ·在vue2中我们必须要有一个根标签,
        ·vue3中我们可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中
        好处:减少标签层级,减小内存占用(多少能较少点吧...)

    Teleport:
        是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术
        场景:像 modals,toast 等这样的元素,很多情况下,我们将它完全的和我们的 Vue 应用的 DOM 完全剥离,管理起来反而会方便容易很多
        原因在于如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难
        另外,像 modals,toast 等这样的元素需要使用到 Vue 组件的状态(data 或者 props)的值
        这就是 Teleport 派上用场的地方
        传送,瞬间移动,玩过lol,王者荣耀的朋友可以稍微联想一哈
   */
};
</script>
<style scoped>
.grand {
  background-color: rgb(150, 156, 154);
  padding: 50px;
}
</style>

Child.vue

<template>
  <div class="child">
    <h2>我是child</h2>
    <button @click="showDialog">显示弹出框木兰辞</button>
    <my-dialog ref="refDialog" :id="123" @confirm="confirm" title="木兰辞">
      <template v-slot:content>
        <div class="msg">
          唧唧复唧唧,木兰当户织。不闻机杼声,唯闻女叹息。
          问女何所思,问女何所忆。女亦无所思,女亦无所忆。昨夜见军帖,可汗大点兵,军书十二卷,卷卷有爷名。阿爷无大儿,木兰无长兄,愿为市鞍马,从此替爷征。
          东市买骏马,西市买鞍鞯,南市买辔头,北市买长鞭。旦辞爷娘去,暮宿黄河边,不闻爷娘唤女声,但闻黄河流水鸣溅溅。旦辞黄河去,暮至黑山头,不闻爷娘唤女声,但闻燕山胡骑鸣啾啾。
          万里赴戎机,关山度若飞。朔气传金柝,寒光照铁衣。将军百战死,壮士十年归。
          归来见天子,天子坐明堂。策勋十二转,赏赐百千强。可汗问所欲,木兰不用尚书郎,愿驰千里足,送儿还故乡。
          爷娘闻女来,出郭相扶将;阿姊闻妹来,当户理红妆;小弟闻姊来,磨刀霍霍向猪羊。开我东阁门,坐我西阁床,脱我战时袍,著我旧时裳。当窗理云鬓,对镜帖花黄。出门看火伴,火伴皆惊忙:同行十二年,不知木兰是女郎。
          雄兔脚扑朔,雌兔眼迷离;双兔傍地走,安能辨我是雄雌?
        </div>
      </template>
    </my-dialog>
    <son></son>
  </div>
</template>

<script>
import Son from "./Son.vue";
import MyDialog from "./MyDialog.vue";
import {ref} from "vue";

export default {
  components: {Son, MyDialog},
  setup() {
    let refDialog = ref(null);

    function showDialog() {
      refDialog.value.open();
    }

    function confirm() {
      console.log("点击了确定按钮");
      refDialog.value.close();
    }

    return {refDialog, showDialog, confirm};
  },
};
</script>

<style scoped>
.child {
  background-color: rgb(22, 129, 201);
  padding: 50px;
}
</style>

Son.vue

<template>
  <h3 class="son">我是son</h3>
  <button @click="showDialog">显示弹出框出师表</button>
  <my-dialog ref="refDialog" :id="123" @confirm="confirm" title="出师表">
    <template v-slot:content>
      <div class="msg">
        先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
        宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
        侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。
        将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
        亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。
        臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
        先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐托付不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
        愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言。深追先帝遗诏,臣不胜受恩感激。
        今当远离,临表涕零,不知所言。
      </div>
    </template>
  </my-dialog>
</template>

<script>
import MyDialog from "./MyDialog.vue";
import {ref} from "vue";

export default {
  components: {MyDialog},
  setup() {
    let refDialog = ref(null);

    function showDialog() {
      refDialog.value.open();
    }

    function confirm() {
      console.log("点击了确定按钮");
      refDialog.value.close();
    }

    return {refDialog, showDialog, confirm};
  },
};
</script>

<style scoped>
.son {
  background-color: rgb(218, 199, 29);
  padding: 20px 0;
}

.msg {
  color: brown;
  line-height: 30px;
}
</style>

MyDialog.vue

<template>
  <teleport to="body">
    <div class="mask" v-if="isShow">
      <div class="dialog">
        <div class="header">{{ title }}</div>
        <div class="content">
          <slot name="content"></slot>
        </div>
        <div class="footer">
          <button @click="close">取消</button>
          <button @click="confirm">确定</button>
        </div>
      </div>
    </div>
  </teleport>
</template>

<script>
/* 
  使用teleport移动至设置元素所在位置
*/
import { ref } from "vue";
export default {
  props: {
    id: {
      type: Number,
      default: null,
    },
    title: {
      type: String,
      default: "提示",
    },
  },
  emits: ["confirm"],
  setup(props, { emit }) {
    let isShow = ref(false);

    getData();
    function getData() {
      console.log("拿到的id===>", props.id);
    }
    function open() {
      isShow.value = true;
    }
    function close() {
      isShow.value = false;
    }
    function confirm() {
      emit("confirm");
    }
    return { isShow, open, close, confirm };
  },
};
</script>

<style scoped>
.mask {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 99;
}
.dialog {
  width: 500px;
  background-color: #fff;
  border-radius: 10px;
  padding: 20px;
}

.header {
  text-align: center;
  font-size: 23px;
  font-weight: bold;
}

.content {
  max-height: 300px;
  overflow: auto;
  margin: 20px 0;
}

.footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  height: 50px;
}

.footer > button {
  margin-left: 10px;
  width: 80px;
  height: 30px;
}
</style>

可能还会有人疑惑,Teleport标签到底有什么用?请看下图

去掉teleport标签对,审查元素,看看弹出框的位置

可以看出来dialog元素在引用的父组件下,但是这样带来的效果并不是很好,比如会被父组件中的某些css样式影响到,在elementui的dialog组件中我们会见到这两个属性 

在vue3中我们利用teleport可以轻易的达到此目的,请看加上teleport后,dialog组件已经和app处于同级关系

 结束!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue3 Form-Create-Designer是一个基于Vue3的表单设计器,支持自定义组件。如果你想要添加自定义组件,可以按照以下步骤进行操作: 1. 创建自定义组件 首先需要创建一个Vue3组件,可以通过Vue CLI等工具进行创建。在组件内部实现自己的功能和样式,并在最后通过export default导出该组件。 例如,我们创建了一个名为MyInput的组件: ```vue <template> <div> <input v-model="value" :placeholder="placeholder" /> </div> </template> <script> import { defineComponent } from 'vue' export default defineComponent({ props: { value: { type: String, default: '' }, placeholder: { type: String, default: '请输入' } } }) </script> <style scoped> div { border: 1px solid #ccc; padding: 10px; } input { width: 100%; height: 32px; border: none; border-bottom: 1px solid #ccc; } </style> ``` 2. 注册自定义组件 在使用Form-Create-Designer的页面中,需要通过Vue3的全局组件注册方式来注册自定义组件。在代码中引入MyInput组件,并使用Vue3的component方法进行注册。 例如: ```vue <template> <div> <form-create-designer v-model="form" :schema="schema" /> </div> </template> <script> import { defineComponent } from 'vue' import FormCreateDesigner from 'vue3-form-create-designer' import MyInput from './MyInput.vue' export default defineComponent({ components: { FormCreateDesigner, MyInput }, data() { return { form: {}, schema: { fields: [ { type: 'MyInput', model: 'input', label: '自定义输入框' } ] } } } }) </script> ``` 在上面的代码中,我们将MyInput组件注册为全局组件,并在schema中使用了type为MyInput的自定义组件。 3. 使用自定义组件 在注册好自定义组件后,就可以在Schema中使用该自定义组件了。可以在Schema中使用type属性指定该字段的类型为我们刚刚注册的自定义组件。 例如: ```js { type: 'MyInput', model: 'input', label: '自定义输入框' } ``` 这样就可以在Form-Create-Designer中使用自定义组件了。 希望这个回答对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay丶萧邦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值