vue模块化开发以及组件、指令封装思想

js模块化开发

为什么会有模块化开发?

  1. 代码重用时,引入js文件的数目可能少了,避免来代码的累赘。
  2. 代码复用高,开发效率也会提高。
  3. 方便后期的维护。
    模块化开发

模块化封装(组件封装)思想

  1. 智能组件
  • 和一切数据打交道,发生各种请求。
  • 只接受父组件的参数。返回给父组件需要的值。
  1. 木偶组件
  • 不依赖父组件的实例,不受父组件影响(css)。
  • 接受父组件的一切,不返回任何值。
  • 渲染确定的结果。
    页面渲染通过智能组件。它们专门做数据相关的应用逻辑,和各种数据打交道、和 Ajax 打交道,然后把数据通过 props 传递给木偶组件,它们带领着 木偶组件组件完成了复杂的应用程序逻辑
    组件封装一个react-redux组件封装介绍使用;

vue组件封装实例

需要对vue的指令有更生的理解:

extend:组件构造器;
directive:指令生成器;
slot:组件插槽;
style,class绑定;

组件封装思想:model层,view层,control层

1. vue组件封装: message封装。

已经实现:自定义样式,自定义内容,以方法调用

model层实现

<template>
  <transition name="mei-message-fade">
    <div v-if="show" :class="[
        'mei-message',
        type? `mei-message-${ type }` : '']">
      <span class="mei-message-con">{{text}}</span>
    </div>
  </transition>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component
export default class MessageBox extends Vue {
  show: boolean = false;
  text: string = '';
  type: string = '';
}
</script>
<style>
  .mei-message {
  }

  .mei-message-success {
  }

  .mei-message-error {
  }

  .mei-message-warning {
  }

  .mei-message-icon {
  }

  .mei-message-con {
    line-height: 40px;
    height: 40px;
    display: inline-block;
    margin-left: 10px;
  }

  .mei-message-fade-enter-active {
    transition: all 0.3s linear;
  }

  .mei-message-fade-leave-active {
    transition: all 0.3s linear;
  }

  .mei-message-fade-enter, .mei-message-fade-leave-to
    /* .slide-fade-leave-active for below version 2.1.8 */
  {
    opacity: 0;
  }
</style>

show: boolean = false; 控制组件的显示隐藏
text: string = ''; 组件的显示文字
type: string = '';组件显示类型
这是个典型的木偶组件,依赖三个参数;它只负责页面的渲染;给什么渲染什么。

control层实现:

import Vue from 'vue';
import messageVue from '@/components/MessageBox.vue'; // 组件引入

interface Star {  ts接口声明
  show?: boolean;
  text?: string;
  duration?: string;
  type?: string;
}

export const messageBox = (options: Star) => {
  const defaults = {
    show: false,
    text: '',
    duration: '2000',
    type: ''
  };
  const messageVueConstructor = Vue.extend(messageVue);//  实现组件构造
  if (Vue.prototype.$isServer) {
    return;
  }
  options = Object.assign({}, defaults, options); // 配置参数
  const parent = document.body;
  const instance = new messageVueConstructor({ // 组件的实例
    el: document.createElement('div'),
    data: options
  });
  parent.appendChild(instance.$el);// 插入页面
  Vue.nextTick(() => {
    instance.show = true; // 修改显示和隐藏
    setTimeout(function () {
      // (<any>instance).show=false;
      instance.show = false;
    }, options.duration);
  });
  return instance;
};

export default {
  install: vue => {
    vue.prototype.$message = messageBox; // 将message组件暴露出去,并挂载在Vue的prototype上
  }
};

首先需要我们引入组件,然后通过构造实例来形成组件,通过组件的实例来控制组件的显示和隐藏。
最后我们把实例的方法导出去;同时挂载导vue的原型;的在main.ts里面引入,通过use使用。这样我们就封装好来一个属于我们自己的$message

import message from './util/message';
Vue.use(message);

最后我们通过vm.$message()就可以使用了;

view层实现

vm.$message({type:'success',text:'xxx',duration:3333})

2. vue指令封装 v-loading

可以实现:添加修饰符,样式修改,内容添加

model层

<template>
  <div v-show="visible" class="zh-loading-box" v-bind:class="{full:body}">
    <div class="flex-center">
      <div>
        <h1>加载</h1>
      </div>
      <p>{{ text }}</p>
    </div>
  </div>
</template>

<script lang='ts'>
import { Component, Vue } from 'vue-property-decorator';

@Component
export default class Load extends Vue {
  text: string = '';
  body: boolean = true;
  visible: boolean = false;
}
</script>

<style scoped>
  .zh-loading-box {
    position: absolute;
     100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.8);
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
  }
</style>

这也是个木偶组件;对传入的参数进行显示;

control层

import Load from '@/components/Load.vue';

const toggleLoading = (el, binding) => {
  if (binding.modifiers.body) {
    el.instance.body = true;
  } else {
    el.instance.body = false;
  }
  if (binding.value) {
    el.instance.visible = true;
  } else {
    el.instance.visible = false;
  }
};

export default {
  install: vue => {
    vue.directive('loading', {
      bind: (el, binding) => {
        const defaults = {
          visible: false,
          body: false,
          text: el.getAttribute('loading-text')
        };
        const options = Object.assign({}, defaults);
        const LoadingCounstruct = vue.extend(Load);
        const loading = new LoadingCounstruct({
          el: document.createElement('div'),
          data: options
        });
        el.style.position = 'relative';
        el.appendChild(loading.$el);
        el.instance = loading; // el.instance是个Vue实例
        toggleLoading(el, binding);
      },
      update: (el, binding) => {
        // el.instance.setText(el.getAttribute('loading-text'));
        if (binding.oldValue !== binding.value) {
          toggleLoading(el, binding);
        }
      }
    });
  }
};

指令的实现是通过 vue.directive来实现的

Vue.directive('my-directive', {
  bind: function () {},
  inserted: function () {},
  update: function () {},
  componentUpdated: function () {},
  unbind: function () {}
})

这个是它的生命周期;钩子函数的参数 ( el、binding、vnode 和 oldVnode)。

bind只调用一次,指令第一次绑定到元素时调用。
update在指令的传入值更新的时候实现。

在bind的时候通过调用组件的实例让组件显示,同时获取绑定标签属性来设置显示的文字;和设置标签的样式让组件合理显示,在处理loading显示的时候通过获取修饰符binding.modifiers.body,来对显示元素实现不通的显示效果,

通过对update市设置,让loading隐藏

if (binding.value) {
el.instance.visible = true;
} else {
el.instance.visible = false;
}

最后export default 出去;
在main.ts里面

import loading from './util/loading';
Vue.use(loading);

view层

<div v-loading='true'></div>



作者:熊少年
链接:https://www.jianshu.com/p/0662d0a7b4f3
原文地址:https://www.cnblogs.com/zyx-blog/p/14585073.html