Vue API - extend 開發消息彈窗組件

一般狀況使用vue時都是掛在某個節點下,例如:
App.vuehtml

<body>
    <div id="app"></div>
</body>
複製代碼

main.jsvue

import Vue from "vue";
import App from "./App.vue";
new Vue({
  render: h => h(App)
}).$mount("#app");
複製代碼

藉助webpack vue-loader App.vue將會導出成一個對象App,h函數將App數據渲染成節點再掛載到#app節點下。至此全部頁面操做都在該節點下,包括路由跳轉等等。
可是有時候咱們也可能須要將節點掛載在其餘位置,而非#app上,或者說須要多個能夠掛載vue的節點。
例如咱們須要開發一個相似element-ui的通知組件webpack

這個組件有着以下特色:

  • 頁面每一個地方均可能使用到,不可能每一個頁面都寫alert組件
<!--這裏假設組件名稱爲alert-->
<alert :show="isShow"></alert> 
複製代碼

咱們須要的是這樣調用組件:web

this.$Alert({content:'hello',duration:2})
複製代碼
  • 組件的位置須要fix定位,爲避免這個組件被其餘元素遮住,最理想的狀況是這樣的:
<body>
    <!-- vue渲染區域-->
    <div id="app"></div>
    <!--alert組件渲染區,而且爲fixed定位-->
    <div class="alert"></div>
</body>
複製代碼

因此咱們須要第二個區域使用vue了,Vue提供了extend API 能夠拓展vue實例。 例如在main.js中element-ui

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");

const Tips = Vue.extend({
    template: `<h1>{{message}}</h1>`,
       data() {
         return {
           message: "hello,world"
         };
       }
});
const comp = new Tips().$mount();
document.body.appendChild(comp.$el);
複製代碼

上述代碼便可在渲染出第二塊區域h1,在h1內同樣可使用vue
因此開發思路以下:bash

  1. this.$Alert({}) 調用時new一個Vue 並經過render函數渲染出一個alert組件。
  2. 經過Vue.extend和$mounted掛載上去

main.js 註冊$Alert()app

import { info } from "./components/alert.js";
Vue.prototype.$Alert = info;
複製代碼

alert.js函數

import Vue from "vue";
import Alert from "./alert.vue";

// 向Alert組件傳遞data數據
export const info = options => {
  const Instance = new Vue({
    render(h) {
      return h(Alert, {
        props: options
      });
    }
  });
  const comp = Instance.$mount();
  document.body.appendChild(comp.$el);
  const alert = Instance.$children[0];
  alert.add(options);
};

複製代碼

alert.vue優化

<template>
  <div class="alert">
    <div class="alert-main" v-for="item in notices" :key="item.name">
      <div class="alert-content">{{ item.content }}</div>
    </div>
  </div>
</template>
<script>
import { setTimeout } from "timers";
let seed = 0;
function getUuid() {
  return `alert_${seed++}`;
}
export default {
  data() {
    return {
      notices: []
    };
  },
  methods: {
    add(notice) {
      const uuid = getUuid();
      let _notice = Object.assign({ name: uuid }, notice);
      this.notices.push(_notice);
      const { duration } = _notice; 
      setTimeout(() => {
        this.remove(_notice.name);
      }, duration * 1000);
    },

    remove(name) {
      alert(name);
      const notices = this.notices;
      for (let i = 0; i < notices.length; i++) {
        if (notices[i].name === name) {
          this.notices.splice(i, 1);
          break;
        }
      }
    }
  }
};
</script>
<style>
.alert {
  position: fixed;
  width: 100%;
  top: 16px;
  left: 0;
  text-align: center;
  pointer-events: none;
}
.alert-content {
  display: inline-block;
  padding: 8px 16px;
  background: #fff;
  border-radius: 3px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
  margin-bottom: 8px;
}
</style>
複製代碼

具體頁面使用:ui

this.$Alert({
    content: "這是一條提示信息",
    duration: 3
});
複製代碼

一個最原始的alert組件就實現了,後續可自行優化!

相關文章
相關標籤/搜索