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用户鼠标移入,控制定时关闭

你可能感兴趣的:(element)