在平常,我们使用vue组件的时候,都要先在.vue
文件中引入我们要使用的组件。虽然这样能满足大部分日常开发的需求,但这种方法在某些场景下,就有些难以应对。
- 组件的模板是通过调用接口从服务端获取的,需要动态渲染组件;
- 实现类似原生 window.alert() 的提示框组件,它的位置是在 下,而非 ,并且不会通过常规的组件自定义标签的形式使用,而是像 JS 调用函数一样使用。
extend
Vue.extend 的作用,就是基于 Vue 构造器,创建一个“子类”,它的参数跟 new Vue 的基本一样,但 data 要跟组件一样,是个函数,再配合 $mount ,就可以让组件渲染,并且挂载到任意指定的节点上,比如 body。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import Vue from 'vue';
<!-- 创建了一个构造器,这个过程就可以解决异步获取 template 模板的问题 -->
const AlertComponent = Vue.extend({
template: '<div>{{ message }}</div>',
data () {
return {
message: 'Hello, Aresn'
};
},
});
<!-- 调用 $mount 方法对组件进行了手动渲染, -->
const component = new AlertComponent().$mount();
<!-- 挂载节点 -->
document.body.appendChild(component.$el);
<!-- 快捷的挂载方式 -->
new AlertComponent().$mount('#app');
这样就可以满足我们用js方法调用的方式来控制组件,但是在平常的开发中,我们用的vue的runtime编译环境,不支持template
模板,而且用字符串来描述组件的模板,也有些不太友好。那么,我们可以试试用new Vue()
的方式。
new Vue
new Vue()
也可以直接创建 Vue 实例,并且用一个 Render 函数来渲染一个 .vue 文件。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import Vue from 'vue';
import Notification from './notification.vue';
const props = {}; // 这里可以传入一些组件的 props 选项
const Instance = new Vue({
render (h) {
return h(Notification, {
props: props
});
}
});
const component = Instance.$mount();
document.body.appendChild(component.$el);
这样既可以使用 .vue 来写复杂的组件,还可以根据需要传入适当的 props。渲染后,如果想操作 Render 的 Notification 实例,也是很简单的:1
const notification = Instance.$children[0];
实例
接下来就给大家,看下我在项目中用new Vue()
的方式来实现的弹框组件。首先我们要新建一个vue文件来,完成弹框的基本布局和样式。
modal-dialog
此文件实现了弹框的基本布局,蒙层和关闭事件,弹框内容可以通过插槽来控制,支持的props有width,height,bgSrc(弹框的背景图片),visible,hasClose(是否有关闭‘X’)
1 | <template> |
弹框的基本功能实现后,我们就用它来建一个常用的通知组件 alert-box
。文件中的图片大家自行替换呀。样式方面也请自行调整呀。
1 | <template> |
最后,是重头戏,如何将这个alertBox
的实例挂载在vue的原型上呢?下面我们用new Vue
来实现alert.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43import Vue from "vue";
import AlertBox from "./alertBox.vue";
let contain = document.body,
messageInstance = null,
component = null;
AlertBox.newInstance = properties => {
const props = properties || {};
// props : visible ; textType 传入props visible,我们还可以传入很多的props 详情查看官方文档
const Instance = new Vue({
render(h) {
return h(AlertBox, {
props,
nativeOn: {
"update:visible": function(val) {
// 监听alerBox isShow变化的事件,如果组件隐藏,我们移除挂载节点,并销毁实例
if (!val) {
contain.removeChild(component.$el);
Instance.$destroy();
}
}
}
});
}
});
// 组件渲染
component = Instance.$mount();
// 组件挂载
contain.appendChild(component.$el);
};
// 保证单一实例
function getMessageInstance(props) {
messageInstance = messageInstance || AlertBox.newInstance(props);
}
export default {
// 暴露info方法,后面可以增加新的方法
info(props) {
return getMessageInstance(props);
}
};
最后我们在项目的main.js文件引入alert.js
1
2import MyAlert from "./components/alert";
Vue.prototype.$myAlert = MyAlert;
就可以在vue文件中,用 this.$myAlert.info()
实现通知弹框了。1
2
3
4this.$myAlert.info({
visible: true,
textArr: ["团队解散失败,请重试"]
});