developing 自定义指令
<template>
<transition name="u-loading-fade">
<div class="developing">
{{ text }}
</div>
</transition>
</template>
<script>
export default {
data() {
return {
text: ''
}
}
}
</script>
<style lang="scss" scoped>
.developing {
position: absolute;
top: 0;
left: 0;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
font-size: 60px;
color: #cccccc8c;
cursor: default;
background: rgba(0, 0, 0, 0.5);
}
</style>
import Vue from 'vue'
import DevelopingComponent from './developing.vue'
const DevelopingConstructor = Vue.extend(DevelopingComponent)
export default () => {
Vue.directive('developing', function(el, binding) {
if (el.getElementsByClassName('developing').length === 0) {
const instance = new DevelopingConstructor({
el: document.createElement('div'),
data: {}
})
Vue.nextTick(() => {
console.log(instance) // VueComponent实例化参数
el.appendChild(instance.$el)
el.instance = instance
el.style.setProperty('position', 'relative', 'important')
el.instance.$el.style.setProperty('position', 'absolute', 'important')
el.instance.text = binding.value
})
}
})
}
src/directive/index.js
import Vue from 'vue'
import developing from './developing'
Vue.directive('developing', developing) // 暂未接入
src/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './directive' // 全局指令注册
Vue.prototype.$mapView = {
map: {},
map1: {},
map2: {}
}
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
指令钩子函数说明
具体可以查看https://cn.vuejs.org/v2/guide/custom-directive.html,这里不累赘。
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
我们会在稍后讨论渲染函数时介绍更多 VNodes 的细节。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
接下来我们来看一下钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。
Vue.extend 构造器
构造器简单例子
// 创建构造器
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')
为什么使用 extend
在 vue 项目中,我们有了初始化的根实例后,所有页面基本上都是通过 router 来管理,组件也是通过 import 来进行局部注册,所以组件的创建我们不需要去关注,相比 extend 要更省心一点点。但是这样做会有几个缺点:
- 组件模板都是事先定义好的,如果我要从接口动态渲染组件怎么办?
- 所有内容都是在 #app 下渲染,注册组件都是在当前位置渲染。如果我要实现一个类似于 window.alert() 提示组件要求像调用
JS 函数一样调用它,该怎么办?
这时候,Vue.extend + vm.$mount 组合就派上用场了。
import Vue from 'vue'
const testComponent = Vue.extend({
template: '<div>{{ text }}</div>',
data: function () {
return {
text: 'extend test'
}
}
})
也可以通过以下这种方式
import DevelopingComponent from './developing.vue' // 具体的vue组件
const DevelopingConstructor = Vue.extend(DevelopingComponent)
然后我们将它手动渲染:
const extendComponent = new testComponent().$mount()
我们可以通过 $el 属性来访问 extendComponent 组件实例:
document.body.appendChild(extendComponent.$el)
VueComponent实例化
import Vue from 'vue'
import DevelopingComponent from './developing.vue'
const DevelopingConstructor = Vue.extend(DevelopingComponent)
export default () => {
Vue.directive('developing', function(el, binding) {
if (el.getElementsByClassName('developing').length === 0) {
const instance = new DevelopingConstructor({
el: document.createElement('div'),
data: {}
})
Vue.nextTick(() => {
console.log(instance) // VueComponent实例化参数
el.appendChild(instance.$el)
el.instance = instance
el.style.setProperty('position', 'relative', 'important')
el.instance.$el.style.setProperty('position', 'absolute', 'important')
el.instance.text = binding.value
})
}
})
}
通过下图可以看到instance 其实就是一个vue组件,具体使用方法可以把instance 等同于组件中的this一样操作