经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue使用Vue.extend创建全局toast组件实例
来源:jb51  时间:2023/3/6 9:13:01  对本文有异议

Vue.extend创建全局toast组件

src -> components -> Toast -> toast.vue

  1. <template>
  2. ? <transition name="fades">
  3. ? ? <div class="Errormes" ?v-if="show">{{txt}}</div>
  4. ? </transition>
  5. </template>
  6. ?
  7. <script>
  8. export default {
  9. ? name: 'Toast',
  10. ? data () {
  11. ? ? return {
  12. ? ? ? txt: '',
  13. ? ? ? show: false
  14. ? ? }
  15. ? }
  16. }
  17. </script>
  18. <style lang="less" scoped>
  19. .fades-enter-active, .fades-leave-active {
  20. ? transition: opacity 0.5s;
  21. }
  22. .fades-enter, .fades-leave-active {
  23. ? opacity: 0;
  24. }
  25. /* 提示弹框 */
  26. .Errormes {
  27. ? position: fixed;
  28. ? top: 40%;
  29. ? left: 50%;
  30. ? -webkit-transform: translate(-50%, -50%);
  31. ? transform: translate(-50%, -50%);
  32. ? padding: 20px 30px;
  33. ? background: rgba(0, 0, 0, 0.8);
  34. ? border-radius: 16px;
  35. ? color: #fff;
  36. ? font-size: 28px;
  37. ? z-index: 999999;
  38. ? max-width: 80%;
  39. ? height: auto;
  40. ? line-height: 60px;
  41. ? text-align: center;
  42. }
  43. </style>

src -> components -> Toast -> index.js

  1. import Toast from './toast.vue'
  2. ?
  3. const toast = {}
  4. toast.install = (vue) => {
  5. ? const ToastClass = vue.extend(Toast)
  6. ? const instance = new ToastClass()
  7. ? instance.$mount(document.createElement('div'))
  8. ? document.body.appendChild(instance.$el)
  9. ?
  10. ? let t = null
  11. ? const ToastMain = {
  12. ? ? show (msg, seconds = 2000) {
  13. ? ? ? if (t) clearTimeout(t)
  14. ? ? ? instance.txt = msg
  15. ? ? ? instance.show = true
  16. ? ? ? t = setTimeout(() => {
  17. ? ? ? ? instance.show = false
  18. ? ? ? }, seconds)
  19. ? ? }
  20. ? }
  21. ? vue.prototype.$toast = ToastMain
  22. }
  23. ?
  24. export default toast

main.js

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import toast from '@/components/Toast/index'
  4. ?
  5. Vue.use(toast)

使用

  1. $toast.show(message)

关于vue.extend的理解应用

基本概念

  1. Vue.extend( options )

使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

一般,我们会用 Vue.extend 接收一个组件对象来创建一个构造器,再利用创建的构造器 new 一个实例,并将这个实例挂载到一个元素上。

官网基本示例

  1. <div id="mount-point"></div>
  2. // 创建构造器
  3. var Profile = Vue.extend({
  4. ? template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  5. ? data: function () {
  6. ? ? return {
  7. ? ? ? firstName: 'Walter',
  8. ? ? ? lastName: 'White',
  9. ? ? ? alias: 'Heisenberg'
  10. ? ? }
  11. ? }
  12. })
  13. // 创建 Profile 实例,并挂载到一个元素上。
  14. new Profile().$mount('#mount-point')

data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数

结果如下:

<p>Walter White aka Heisenberg</p>

应用

Vue.extend 属于 Vue 的全局 API,在实际业务开发中我们很少使用,因为相比常用的 Vue.component 写法使用 extend 步骤要更加繁琐一些。

但是在一些独立组件开发场景中,例如要实现一个类似于 window.alert() 提示组件,要求像调用 JS 函数一样调用它,这时候 Vue.extend + $mount 这对组合就是我们需要去关注的。

1、vue $mount 和 el的区别说明

在应用之前我们先了解一下2个东西 —— $mount 和 el,两者在使用效果上没有任何区别,都是为了将实例化后的vue挂载到指定的dom元素中。

如果在实例化vue的时候指定el,则该vue将会渲染在此el对应的dom中,反之,若没有指定el,则vue实例会处于一种“未挂载”的状态,此时可以通过$mount来手动执行挂载。

注:如果$mount没有提供参数,模板将被渲染为文档之外的的元素,并且你必须使用原生DOM API把它插入文档中。

  1. var MyComponent = Vue.extend({
  2. ?template: '<div>Hello!</div>'
  3. })
  4. ?
  5. // 创建并挂载到 #app (会替换 #app)
  6. new MyComponent().$mount('#app')
  7. ?
  8. // 同上
  9. new MyComponent({ el: '#app' })
  10. ?
  11. // 或者,在文档之外渲染并且随后挂载
  12. var component = new MyComponent().$mount()
  13. document.getElementById('app').appendChild(component.$el)

2、Vue.extend实现Loading插件($mount)

  1. <div id="root">
  2. ? ? <button @click="showLoading">显示Loading</button>
  3. </div>
  4. function Loading(msg) {
  5. ? ? ? ? // 创建构造器
  6. ? ? ? ? const Loading = Vue.extend({
  7. ? ? ? ? ? template: '<div id="loading-msg">{{ msg }}</div>',
  8. ? ? ? ? ? props: {
  9. ? ? ? ? ? ? msg: {
  10. ? ? ? ? ? ? ? type: String,
  11. ? ? ? ? ? ? ? default: '加载中'
  12. ? ? ? ? ? ? }
  13. ? ? ? ? ? },
  14. ? ? ? ? ? name: 'Loading'
  15. ? ? ? ? })
  16. ?
  17. ? ? ? ? // 创建挂载div
  18. ? ? ? ? const div = document.createElement('div')
  19. ? ? ? ? div.setAttribute('id', 'loading-div')
  20. ? ? ? ? document.body.append(div)
  21. ?
  22. ? ? ? ? // 创建实例并挂载到一个元素上
  23. ? ? ? ? new Loading().$mount('#loading-div')
  24. ?
  25. ? ? ? ? // 返回一个移除元素的function
  26. ? ? ? ? return () => {
  27. ? ? ? ? ? document.body.removeChild(document.getElementById('loading-div'))
  28. ? ? ? ? }
  29. }
  30. ?
  31. // 挂载到vue实例上
  32. Vue.prototype.$loading = Loading
  33. ?
  34. ?new Vue({
  35. ? ? ?el: '#root',
  36. ? ? ?methods: {
  37. ? ? ? ? showLoading() {
  38. ? ? ? ? ? ? const hide = this.$loading('正在加载,请稍等...')
  39. ? ? ? ? ? ? setTimeout(() => {
  40. ? ? ? ? ? ? ? hide()
  41. ? ? ? ? ? ? }, 1500)
  42. ? ? ? ? }
  43. ? ? ?}
  44. })

3、Vue.extend实现信息弹窗插件(el)

新建一个popBox.vue

  1. <template>
  2. ? <div id="confirm" v-if='flag'>
  3. ? ? <div class="contents" >
  4. ? ? ? <div class="content-top">{{ text.title }}</div>
  5. ? ? ? <div class="content-center">{{ text.msg }}</div>
  6. ? ? ? <div class="content-bottom">
  7. ? ? ? ? <button @click='show' class="left">{{ text.btn.ok }}</button>
  8. ? ? ? ? <button @click='hide' class="right">{{ text.btn.no }}</button>
  9. ? ? ? </div>
  10. ? ? </div>
  11. ? </div>
  12. </template>
  13. ?
  14. <script>
  15. ?
  16. export default {
  17. ? data () {
  18. ? ? return {
  19. ? ? ? flag: true,
  20. ? ? ? text: {
  21. ? ? ? ? ? title:'标题',
  22. ? ? ? ? ? msg: '这是一个信息弹出框组件',
  23. ? ? ? ? ? btn: {
  24. ? ? ? ? ? ? ? ok: '确定',
  25. ? ? ? ? ? ? ? no: '取消'
  26. ? ? ? ? ? }
  27. ? ? ? }
  28. ? ? }
  29. ? },
  30. ?
  31. ? methods: {
  32. ? ? show (){
  33. ? ? ? this.flag = false;
  34. ? ? },
  35. ?
  36. ? ? hide() {
  37. ? ? ? this.flag = false;
  38. ? ? }
  39. ? }
  40. }
  41. ?
  42. </script>

新建一个popBox.js

  1. import Vue from 'vue'
  2. import PopBox from './popBox.vue'
  3. ?
  4. // Vue.extend返回一个实例创建的构造器,但实例构造器需要进行挂载到页面中
  5. let popBox = Vue.extend(PopBox) ??
  6. ?
  7. popBox.install = (vue, text) => {
  8. ? ? ??
  9. ? ? ? ? // 在body中动态创建一个div元素,之后此div将会替换成整个vue文件的内容
  10. ? ? ? ? // 此时的popBoxDom通俗讲就是相当于是整个组件对象,通过对象调用属性的方法来进行组件中数据的使用
  11. ? ? ? ? let popBoxDom = new popBox({
  12. ? ? ? ? ? ? el: document.createElement('div')
  13. ? ? ? ? })
  14. ?
  15. ? ? ? ??
  16. ? ? ? ? // 可以通过$el属性来访问创建的组件实例
  17. ? ? ? ? document.body.appendChild(popBoxDom.$el)
  18. ?
  19. ? ?
  20. ? ? ? ? // 将需要传入的文本内容传给组件实例
  21. ? ? ? ? popBoxDom.text = text;
  22. ?
  23. ? ? ? ? // 返回一个promise,进行异步操作,成功时返回,失败时返回
  24. ? ? ? ? return new Promise((res, rej) => { ? ??
  25. ? ? ? ? ? ? popBoxDom.show = () => { ??
  26. ? ? ? ? ? ? ? ? res() ? //正确时返回的操作
  27. ? ? ? ? ? ? ? ? popBoxDom.flag = false;
  28. ? ? ? ? ? ? }
  29. ?
  30. ? ? ? ? ? ? popBoxDom.hide = ()=>{
  31. ? ? ? ? ? ? ? ? rej() ? //失败时返回的操作
  32. ? ? ? ? ? ? ? ? popBoxDom.flag = false;
  33. ? ? ? ? ? ? }
  34. ? ? ? ? }
  35. ?
  36. ? ? ? ? vue.prototype.$popBox = popBox ? ?
  37. ? ? })
  38. }
  39. ?
  40. // 将逻辑函数进行导出和暴露
  41. export default popBox

页面使用

  1. import PopBox from './popBox.js'
  2. ?
  3. Vue.use(popBOx);
  4. ?
  5. ?
  6. this.$popBox({
  7. ? ? ? title:'标题',
  8. ? ? ? msg:'内容',
  9. ? ? ? btn:{ ok:'确定', no:'取消'}
  10. }).then(()=>{
  11. ? ? ? console.log('ok')
  12. }).catch(()=>{
  13. ? ? ? console.log('no')
  14. })

其他

  1. import toastCom from "./Toast";
  2. ?
  3. const toast = {};
  4. toast.install = vue => {
  5. ?const ToastCon = vue.extend(toastCom);
  6. ?const ins = new ToastCon();
  7. ?ins.$mount(document.createElement("div"));
  8. ?document.body.appendChild(ins.$el);
  9. ?console.log(ins.toast)
  10. ?vue.prototype.$toast = ins.toast;
  11. };
  12. ?
  13. ?
  14. ?
  15. const globalComponent = {
  16. ?install: function(Vue) {
  17. ? ?Vue.use(toast);
  18. ?}
  19. };
  20. ?
  21. export default globalComponent;

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号