Vue 如何以插件的形式编写通用的全局弹框或者loading

Vue.extend 也就是用到这个玩意

请求封装的全局loading

image.png

1.首先是先搞个loading组件 loading.vue

<template>
  <div class="box" v-if='showToast'>
    <div class="load">
      <img src="../assets/test.gif" alt="">
      <div class="load_txt">{{txt}}</div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'Loading',
  data () {
    return {
      showToast: true,
      txt:'Loading'
    }
  },
  methods: {

  }
}
</script>
<style scoped>
.box {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  height: 100%;
  /* background: rgba(0, 0, 0, 0.5); */
}

.load {
  width: 180px;
  height: 180px;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -90px;
  transform: translate(-50%);
}
.load img {
  width: 100%;
}
.load_txt{
  text-align:center;
  color:#e4393c
}
</style>

复制代码

2.新建一个load.js

import Vue from 'vue'
import Loading from '@/components/loading.vue'
const loadPlguin = Vue.extend(Loading)
let instance = new loadPlguin({
  el: document.createElement('div')
})

const load = {
  show(options) {
    instance.showToast = true;
    instance.txt = options.txt //这个是自定义的文案
    document.body.appendChild(instance.$el);
  },
  hide() {
    instance.showToast = false;
    document.body.removeChild(instance.$el);
  }

}
export default {
  install(Vue) {
    Vue.prototype.$toast = load
  }
}

复制代码

3.在main.js中引用

import Toast from './utils/load'
Vue.use(Toast)
复制代码

4.在组件中使用

 getData () {//这里正常应该放到 request封装请求里使用,这里只做个测试
      this.$toast.show({ txt: 'fuck...' })
      fetch('https://random.dog/woof.json')
        .then(res => res.json())
        .then((res) => {
          this.$toast.hide()
          this.url = res.url;
        })
    },
复制代码

通用弹框组件

image.png

1. 新建dialog.vue

<template>
  <div id="confirm" v-if='flag'>
    <div class="contents">
      <div class="content-top">{{content.title}}</div>
      <div class="content-center">{{content.msg}}</div>
      <div class="content-bottom">
        <button type='primary' @click='submit' class="left">{{content.okButtonTxt}}</button>
        <button type='info' @click='cancle' class="right">{{content.noButtonTxt}}</button>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data () {
    return {
      flag: true,
      content: {
        title: '标题',
        msg: '这是一个弹出框组件',
        okButtonTxt: '确定',
        noButtonTxt: '取消',
      }
    }
  },
  methods: {
    submit () {
      this.flag = false;
    },
    cancle () {
      this.flag = false;
    },
  }
}
</script>

<style scoped>
#confirm {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.3);
}
.contents {
  width: 250px;
  height: 180px;
  border: 1px solid #ccc;
  border-radius: 10px;
  background-color: #fff;
  position: fixed;
  top: 50%;
  left: 50%;
  margin-top: -90px;
  margin-left: -125px;
}
.content-top {
  width: 100%;
  height: 40px;
  border-bottom: 1px solid #ccc;
  text-align: center;
  font-size: 20px;
  font-weight: 700;
  line-height: 40px;
}
.content-center {
  width: 90%;
  height: 80px;
  margin: 5px auto;
}
.content-bottom {
  width: 85%;
  height: 40px;
  margin: 0 auto;
  /* border:1px solid red; */
  position: relative;
}
.left {
  position: absolute;
  left: 0;
  width: 40%;
}
.right {
  position: absolute;
  right: 0;
  width: 40%;
}
</style>


复制代码

2.新建 dialog.js

import Vue from 'vue'
import Dialog from '@/components/dialog.vue'
const DialogPlguin = Vue.extend(Dialog);
const confirm = (options) => {
  return new Promise((resolve, reject) => {
    let confirmDom = new DialogPlguin({
      el: document.createElement('div'),
    });
    document.body.appendChild(confirmDom.$el);
    confirmDom.content = {
      ...confirmDom.content, //自带默认的
      ...options, //传入的
    }
    confirmDom.submit = () => {
      // if (options.callBack && typeof options.callBack == 'function') {
      //   resolve()
      //   setTimeout(() => {
      //     confirmDom.flag = false;
      //   }, 3000);
      //   return false
      // }
      resolve()
      confirmDom.flag = false;
    }
    confirmDom.cancle = () => {
      reject()
      confirmDom.flag = false;
    }
  })
}
export default {
  install(Vue) {
    Vue.prototype.$dialog = confirm
  }
}
// console.log(DialogPlguin)
// export default confirm
//Vue.prototype.$dialog=Dialog;

复制代码

3. main.js中引入(也可以不使用插件那边导出这里挂载到原型上)

import Dialog from './utils/dialog'
Vue.use(Dialog)
复制代码

4.组件中使用

this.$dialog({
      title: '你好',
      msg: '我是一个弹框的内容',
      // callBack: this.callBack,
      okButtonTxt: '是',
      noButtonTxt:'否'
    }).then(() => {
      console.log('确认')
    }).catch((err) => {
      console.log('取消')
    })
复制代码

平时使用的一个小技巧,多人协同开发使用方便require.context

image.png

1.首先api文件中是我们的各种请求的函数,多人协作开发时,各自建自己的模块的api,这样联调互相不干扰,不会冲突

2.我们最是要把这些请求挂载到vue的原型上,直接在组件中例如this.$request.getList() 等... 在上图中为了避免起名字重名被覆盖,最好在自己负责的模块放到一个对象中类似于 namespace的命明空间一样,这样我们的模块就里就可以随意起名字了,类似

image.png

在utils中新建一个 request.js这里是拿到 api文件中的所有请求

手动引入太不符合身份,这里动态读取api文件夹中的所有接口

let apiObject = {};
const importAll = r => {
  r.keys().forEach(key => Object.assign(apiObject, r(key).default));
};
importAll(require.context("../api", false, /\.js$/));
export default {
  ...apiObject,
};
复制代码

main.js

import request from "./utils/request";
Vue.prototype.$request = request;
复制代码

组件中使用

image.png

async getDetail(id){
    let res=await this.$request.getSignDetail(id);
}
复制代码

Supongo que te gusta

Origin juejin.im/post/7076288644016766984
Recomendado
Clasificación