elementUI的Loading组件就是extend的最好实践
那么我们来实现一个全局组件
新建文件
<template>
<div>
</div>
</template>
<script>
export default {
name: "Test",
props:{
test:String
}
}
</script>
<style scoped lang="scss">
</style>
导入文件
<template>
<div>
</div>
</template>
<script>
import Test from './Test'
import Vue from "vue";
export default {
name: 'EmptyHome',
created() {
const instant = Vue.extend(Test)
const vm = new instant()
console.log(vm);
}
}
</script>
<style scoped lang="scss">
</style>
这样就打印出来了
给全局组件传入props
const instant = Vue.extend(Test)
const vm = new instant()
vm.test = "5555"
console.log(vm);
挂载节点
vm.test = "5555"
this.$refs.rootRef.append(vm.$mount().$el)
console.log(vm);
<template>
<div>
{{test}}
</div>
</template>
<script>
export default {
name: "Test",
props:{
test:String
}
}
</script>
<style scoped lang="scss">
</style>
在全局组件里面使用路由
created() {
console.log(this.$route);
}
打印出来的是一个空,无法读取到
打开vue的开发工具查看一下
这个组件并不在vue的节点树中
使用定位,可以定位到,但是节点树也是没有的
那么我们添加父级
const instant = Vue.extend(Test)
const vm = new instant({
parent: this
})
vm.test = "5555"
this.$refs.rootRef.append(vm.$mount().$el)
console.log(vm);
路由打印出来了,树里面也可以找到,但是给props赋值报警告,这个警告其实就是我们不能直接修改props的警告
那么我们就不要父级,然后路由直接导入使用
import Test from './Test'
import Vue from "vue";
import router from "@/router";
export default {
name: 'EmptyHome',
mounted() {
const instant = Vue.extend(Test)
const vm = new instant({
router: router
})
vm.test = "5555"
this.$refs.rootRef.append(vm.$mount().$el)
console.log(vm);
}
}
正常打印
也就可以正常使用路由
使用vuex
同路由的使用
我们直接导入
import Test from './Test'
import Vue from "vue";
import store from "@/store";
export default {
name: 'EmptyHome',
mounted() {
const instant = Vue.extend(Test)
const vm = new instant({
store
})
vm.test = "5555"
this.$refs.rootRef.append(vm.$mount().$el)
console.log(vm);
}
}
<template>
<div>
{{test}}
<div>
vuex: {{$store.getters.getTest}}
</div>
</div>
</template>
<script>
export default {
name: "Test",
props:{
test:String
},
created() {
}
}
</script>
<style scoped lang="scss">
</style>
页面正常使用
销毁全局组件
<template>
<div>
<div>
<el-button @click="addCom">添加组件</el-button>
<el-button @click="removeCom">销毁组件</el-button>
</div>
<div ref="rootRef">
</div>
</div>
</template>
<script>
import Test from './Test'
import Vue from "vue";
import store from "@/store";
export default {
name: 'EmptyHome',
data(){
return{
vms:[]
}
},
methods:{
addCom(){
const instant = Vue.extend(Test)
const vm = new instant({
store
})
vm.test = "5555"
this.$refs.rootRef.append(vm.$mount().$el)
console.log('添加组件',vm);
this.vms.push(vm)
},
removeCom(){
const vm = this.vms.shift()
vm.$destroy()
console.log('销毁组件',vm);
}
}
}
</script>
<style scoped lang="scss">
</style>
打印了但是dom没有消失
官网有解释,不会消除dom元素,所以dom我们自己消除
removeCom(){
const vm = this.vms.shift()
const el = vm.$el
el.remove() // 移除dom
vm.$destroy()
console.log('销毁组件',vm);
}
正确销毁
当然有的时候组件销毁是自己发出通知----比如全局ELementUI的loading
那么就是要监听事件然后处理,当然也可以写在组件内部处理
<template>
<div>
<div>
<el-button @click="addCom">添加组件</el-button>
</div>
<div ref="rootRef">
</div>
</div>
</template>
<script>
import Test from './Test'
import Vue from "vue";
import store from "@/store";
export default {
name: 'EmptyHome',
data(){
return{
data: 1
}
},
methods:{
addCom(){
const instant = Vue.extend(Test)
const vm = new instant({
store
})
// vm.$on('removeCom',this.removeCom) // 监听事件
vm.test = "5555" + this.data++
this.$refs.rootRef.append(vm.$mount().$el)
console.log('添加组件',vm);
},
removeCom(vm){
const el = vm.$el
el.remove() // 移除dom
vm.$destroy()
console.log('销毁组件',vm);
}
}
}
</script>
<style scoped lang="scss">
</style>
<template>
<div>
{{test}}
<el-button @click="removeCom">销毁组件</el-button>
<div>
vuex: {{$store.getters.getTest}}
</div>
</div>
</template>
<script>
export default {
name: "Test",
props:{
test:String
},
methods:{
removeCom(){
this.$emit('removeCom',this)
this.$el.remove() // 自行处理
this.$destroy()
}
}
}
</script>
<style scoped lang="scss">
</style>
总结
这样我们就可以自己做全局组件,适配一些改动大,到处都要用,跨模块使用的组件,这样包装出来的组件就可以直接放在一个函数上面,在挂载到Vue的原型链上面,就到处都可以调用和使用,最后就变成一行代码就可以搞定
最后
这个东西肯定很少用到的,不过会比不会好\(^o^)/~