js模块化开发
为什么会有模块化开发?
- 代码重用时,引入js文件的数目可能少了,避免来代码的累赘。
- 代码复用高,开发效率也会提高。
- 方便后期的维护。
模块化开发
模块化封装(组件封装)思想
- 智能组件
- 和一切数据打交道,发生各种请求。
- 只接受父组件的参数。返回给父组件需要的值。
- 木偶组件
- 不依赖父组件的实例,不受父组件影响(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;
width: 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>