02 element-ui源碼思路 el-notification

用法特殊性,這類組件不需要在父組件‘template’中引用。可以直接調用。

this.$notify({
          title: '提示',
          message: '這是一條不會自動關閉的消息',
          duration: 0
        });

1.顯示出彈窗

main.js文件


//1.main.vue是彈出框的組件
import Main from './main.vue';

//2.繼承得到main.vue的構造器。Vue.extend用法見vue文檔
const NotificationConstructor = Vue.extend(Main);

//3. this.$notify的實際調用對象
const Notification = function(options) {
  if (Vue.prototype.$isServer) return;
  options = options || {};
  const userOnClose = options.onClose;
  const id = 'notification_' + seed++;
  const position = options.position || 'top-right';
  
/*  4. 通過函數參數傳入的options,通過2.得到的構造器新建一個對象,
     這裏的options對象與main.vue中的按混入形式存在。*/
  instance = new NotificationConstructor({
    data: options
  });
  instance.id = id;
  // 5.見vue文檔。$mount的部分。$mount()、Vue.extend(xxx)配合使用。
  // 當$mount()沒有傳入id選擇器時,在文檔之外渲染並且隨後掛載
  instance.$mount();
  document.body.appendChild(instance.$el);
  
  // 6.到這裏就完成main.vue的顯示,下面是對多個對象同時顯示時,位置的管理。
  instance.visible = true;
  instance.dom = instance.$el;
  instance.dom.style.zIndex = PopupManager.nextZIndex();

// 對顯示的位置進行管理,避免重疊
  let verticalOffset = options.offset || 0;
  // 按邏輯,這裏filter得到的,必然是一個或0個。一般的,如果是0,if判斷跳過foreach。
  // 這裏的的寫法算是一種簡化,讓forEach自行判斷。
  instances.filter(item => item.position === position).forEach(item => {
    verticalOffset += item.$el.offsetHeight + 16;
  });
  verticalOffset += 16;
  
  instance.verticalOffset = verticalOffset;
  instances.push(instance);
  return instance;
};

main.js的是爲了管理這些main.vue而存在的,比如上文提到的 顯示的位置管理,還有關閉的管理。

2.顯示出不同內容

調用this.$notify(‘xxx’),這樣’xxx’就可以顯示出來。

2.1參數爲options對象

使用方式如下

 this.$notify({
          title: '提示',
          message: '這是一條不會自動關閉的消息',
          duration: 0
        });

main.js文件
把options對象中的屬性 合併 到vue的data中。message、title和duration將覆蓋main.vue中的data。

  instance = new NotificationConstructor({
    data: options
  });

main.vue文件
1.如果message是普通字符串,直接顯示
2.message是html格式字符串,需要設置dangerouslyUseHTMLString=true, v-html="message"將輸出這段html代碼

<div class="el-notification__content" v-show="message">
 <slot>
    <p v-if="!dangerouslyUseHTMLString">{{ message }}</p>
    <p v-else v-html="message"></p>
  </slot>
</div>
        
data() {
 return {
   title: '',
   message: '',
   dangerouslyUseHTMLString: false,
   duration: 3000,
 };

2.2參數爲 VNode

使用方式如下

 const h = this.$createElement;

        this.$notify({
          title: '標題名稱',
          message: h('i', { style: 'color: teal'}, '這是提示示文案')
        });

main.js文件
$slots.default是插槽的默認對象,非具名插槽都會顯示到default中,所以defalut爲一個數組。
想修改插槽中的內容,如下,可對$slots.default重新賦值。賦值後內容並不會顯示出來,需要觸發一次渲染。

  if (isVNode(options.message)) {
    instance.$slots.default = [options.message];
    options.message = 'REPLACED_BY_VNODE';
  }

觸發渲染

options.message = ‘REPLACED_BY_VNODE’;引發一次觸發渲染。
因爲main.vue中v-show=‘message’,message 的改變觸發渲染。

<div class="el-notification__content" v-show="message">
 <slot>
    <p v-if="!dangerouslyUseHTMLString">{{ message }}</p>
    <p v-else v-html="message"></p>
  </slot>
</div>

補充

message不光從’’(空字符,false),變成字符串‘REPLACED_BY_VNODE’(true)觸發的。message任意的改變值都會觸發,只要與之前不同。

觸發渲染另一種方式

$slots.default 賦值後,調用官方提供的vm.$forceUpdate(),將刷新 當前組件 和 插槽 ,不刷新 當前組件 的 子組件(見vue文檔),這種方式效率低

this.$slots.default = [vnode]
vm.$forceUpdate()

3.notification移除

3.1當notification消失後,過段時間將被移除;

main.vue文件
需要用到的字段,duration爲3秒

data() {
      return {
        visible: false,
        duration: 3000,
        showClose: true,
        // 屬於main.js的回調函數
        onClose: null,
        onClick: null,
        closed: false,
        timer: null,
        position: 'top-right'
      };

鉤子函數,setTimeout超時duration後關閉調用close()

mounted() {
      if (this.duration > 0) {
        this.timer = setTimeout(() => {
          if (!this.closed) {
            this.close();
          }
        }, this.duration);
      }
      document.addEventListener('keydown', this.keydown);
    },

這裏this.onClose()的是,由main.js(notification管理器)傳入的 一個回調函數

close() {
        this.closed = true;
        if (typeof this.onClose === 'function') {
          this.onClose();
        }
      },

main.js文件
options.onClose 定義回調函數。new NotificationConstructor()將把onClose混入到instance(notification對象)中

options.onClose = function() {
    Notification.close(id, userOnClose);
  };
instance = new NotificationConstructor({
    data: options
  });

3.2用戶手動關閉消息

3.3用戶鼠標移入,控制定時關閉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章