组件
参考elementUI,将组件函数化
<template>
<div>
<ui-mask :show="ownShow"></ui-mask>
<div class="fin-ui-dialog" v-show="ownShow" :transition="animate" @touchmove="preventTouchMove($event)">
<div class="title" v-if="title">
{{ title }}
</div>
<div class="content">
<slot name="content">
<div v-html="content"></div>
</slot>
</div>
<div class="foot clearfix" v-if="foot">
<div>
<button
v-if="showOk"
class="fin-ui-button default small-one"
@click.stop="eventEmitter('ok')"
:disabled="disable"
>
{{ ok }}
</button>
<button
v-if="showCancel"
class="fin-ui-button primary small-one cancle"
@click.stop="eventEmitter('cancel')"
>
{{ cancel }}
</button>
</div>
</div>
</div>
</div>
</template>
<script>
/**
* @file ui-dialog
* @author ienix(guoaimin01@baidu.com)
* @since 9/21
*/
/**
* ui-dialog dialog组件
* @module fin-ui/ui-dialog
*
* @property {boolean} show.sync - 显示或隐藏, 默认隐藏, 传入必须为双向数据绑定类型
* @property {boolean} close - 启用关闭
* @property {boolean} mask - 启用mask
* @property {boolean} head - 启用head
* @property {boolean} foot - 启用foot
* @property {string} type - 模态对话框的形态 [lightbox|dialog|alert|confirm|prompt]
* @property {string} title - 标题
* @property {string|html} content - 对话框内容
* @property {string} ok - 确定的文本
* @property {string} cancel - 取消的文本
* @property {string} animate - 动画方式,默认fade
* @property {string} prefix - 添加css 前缀
* @property {number} width -宽度默认值300
* @property {number} top - 默认垂直居中
*/
/**
* @example
*
* 使用content 扩展内容
*
* 1. 使用文本
* <ui-dialog type="confirm" content="hello world"></ui-dialog>
* 2. html
* <ui-dialog type="confirm" content="<img src="" />"></ui-dialog>
*
* 使用插槽扩展
*/
import uiMask from 'fin-ui/ui-mask';
export default {
props: {
title: {
type: String,
default: ''
},
content: {
type: String,
default: ''
},
animate: {
type: String,
default: 'fade'
},
ok: {
type: String,
default: '确定'
},
cancel: {
type: String,
default: '取消'
},
foot: {
type: Boolean,
default: true
},
showOk: {
type: Boolean,
default: true
},
showCancel: {
type: Boolean,
default: true
},
show: {
type: Boolean,
default: false
},
lightUp: {
type: Boolean,
default: false
}
},
data() {
return {
is: 'ui-dialog',
ownShow: false,
disable: true
};
},
watch: {
show: {
immediate: true,
handler(val) {
this.ownShow = val;
}
},
ownShow: {
immediate: true,
handler(val) {
this.$emit('update:show', val);
}
},
lightUp: {
handler(val) {
this.disable = val;
},
immediate: true
}
},
methods: {
preventTouchMove(event) {
if (this.preventDefaultTouchMove) {
event.preventDefault();
}
},
showUi() {
this.ownShow = true;
},
hideUi() {
this.ownShow = false;
},
eventEmitter(type) {
if (type === 'cancel') {
this.ownShow = false;
}
this.$emit(type, this);
}
},
computed: {},
created() {},
components: {
uiMask
}
};
</script>
<style lang="less" scoped rel="stylesheet/less">
@import '../css/variable.less';
@import '../css/button.less';
@import '../css/util.less';
@name: ~` '@{prefix}' + 'ui-dialog' `;
.@{name} {
background: @white-color;
position: fixed;
z-index: @z-index-primary;
border-radius: @border-radius-default;
font-size: @font-size-18;
top: 50%;
left: 37px;
right: 38px;
margin: 0 auto;
padding: @spacing-5x @spacing-5x+1;
text-align: center;
transform: translateY(-50%);
.title {
display: block;
margin: 0 auto;
text-align: center;
font-weight: 600;
font-size: @font-size-17;
line-height: 24px;
font-family: @font-family-FDC-bold;
color: @text-color-default;
}
.content {
display: inline-block;
margin-top: 13px;
font-size: @font-size-16;
line-height: 23px;
text-align: left;
font-family: @font-family-PingFangSC;
color: @decoration-color-level-three;
}
.foot {
margin-top: 13px;
padding-left: 4px;
padding-right: 4px;
.cancle {
font-family: @font-family-PingFangSC;
}
}
}
</style>
/**
* 1。使用一次后可以把实例存储,修改实例的属性即可
* 2。再次调用vue也是使用这个实例并造成混乱
*/
import Vue from 'vue';
import { Promise } from 'es6-promise';
import assign from 'object-assign';
import dialog from '@/fin-ui/ui-dialog';
import waring from '@/fin-ui/ui-waring';
import loading from '@/fin-ui/ui-loading';
import toast from '@/fin-ui/ui-toast';
let uiMap = {
dialog: dialog,
loading: loading,
toast: toast,
waring: waring
};
Object.keys(uiMap).forEach(name => {
let ui = uiMap[name];
uiMap[name] = options => {
//使用vue构造器,创建一个子类
let componentConstructor = Vue.extend(ui); // 参考elementUi 写法
//实例化
let instance = new componentConstructor();
if (typeof options === 'string') {
options = {
content: options
};
}
assign(instance, options);
instance.$mount();
document.body.appendChild(instance.$el);
//外部一引入,则将组件显示在页面上
instance.showUi();
if (options) {
options.onOk && instance.$on('ok', options.onOk);
options.onShow && instance.$on('show', options.onShow);
options.onHide && instance.$on('hide', options.onHide);
// todo: 这里是否需要将dom上的元素删除掉?
// instance.$on('update:show', val => {
// if (val === false) {
// document.body.removeChild(instance.$el);
// }
// console.log(val + 'show---');
// });
options.onCancel && instance.$on('cancel', options.onCancel);
}
return new Promise((resolve, reject) => {
instance.$on('ok', event => resolve(instance));
instance.$on('show', event => resolve(instance));
instance.$on('hide', event => resolve(instance));
instance.$on('cancel', event => reject(instance));
if (name !== 'dialog' && name !== 'waring') {
return resolve(instance);
}
});
};
});
export default uiMap;
用法
let loading = ui.loading({
type: 'new',
title: '正在完成额度审批',
content: '培养良好信誉,可提高申请成功率',
opacity: 0,
showClose: true,
//在此处进一步定义每一次组件进行使用的时候的差异化处理
onHide: () => {
console.log(this.showLoading + '99999');
}
});
setTimeout(() => {
loading.then(vm => {
vm.hideUi();
});
}, 20000);
整体思想:
1、组件函数化,引用更加方便;
2、在组件内部定义公共的事件发生时的方法,在外部传入,每个组件事件发生时不同的处理方式更加灵活;
3、通过普通的组件编写方法,再将组件套入此方法中,可以实现一套代码,两种引用方式,便于代码的书写以及阅读;
知识点涉及
Vue.extend(options)
用法: 使用基础Vue构造器,创建一个‘子类’,参数是一个包含组件选项的对象
data选项是特例,需要注意,在Vue.extend()中,他必须是函数
<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
vm.$mount( [elementOrSelector] )
用法:
如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可以使用 vm.$mount() 手动地挂载一个未挂载的实例。
如果没有提供 elementOrSelector 参数,模板将被渲染为文档之外的的元素,并且你必须使用原生 DOM API 把它插入文档中。
这个方法返回实例自身,因而可以链式调用其它实例方法。
实例:
var MyComponent = Vue.extend({
template: '<div>Hello!</div>'
})
// 创建并挂载到 #app (会替换 #app)
new MyComponent().$mount('#app')
// 同上
new MyComponent({ el: '#app' })
// 或者,在文档之外渲染并且随后挂载
var component = new MyComponent().$mount()
document.getElementById('app').appendChild(component.$el)