情形: 有一个项目分PC和H5两部分,PC端打开,左侧是一个模拟的手机界面(空白的div),右侧是一系列的各种组件,比如table样式1组件,table样式2组件...各种组件,把右侧组件拖入空白手机界面,保存后,打开对应的H5链接,就可以看到刚才拖拽的页面。
其中的难点就是,拖入的组件是未知的,又不能提前把组件库上百个组件都提前加载。
// router/index.js
![](https://img.haomeiwen.com/i15162177/c387c08f11ad52a1.png)
// all.vue
<template>
<div class="page">
<p style="padding: 1em; font-size: 30px; text-align: center">
all
</p>
<!--<bg1></bg1>-->
<LoadComs v-for="(item, i) in comsArr" :key="i"
:comInfo="item"></LoadComs>
</div>
</template>
<script>
// @ is an alias to /src
// import bg1 from './coms/bg1.vue'
import LoadComs from './coms/LoadComs.vue'
import Vue from 'vue'
export default {
name: 'all',
components: {
// bg1,
LoadComs
},
data () {
return {
comsArr: []
}
},
created () {
console.log(LoadComs, LoadComs.constructor === Vue.component)
setTimeout(() => {
this.comsArr = [
{
name: 'bg1'
}
]
}, 1000)
setTimeout(() => {
this.comsArr = [
{
name: 'bg1',
props: {
color: '#f0a00a'
}
}
]
}, 3000)
setTimeout(() => {
this.comsArr.push({
name: 'bg1',
props: {
color: '#eee',
children: [
{
name: 'bg2',
props: {
color: '#f00',
data: []
}
},
{
name: 'bg3',
props: {
color: '#f1facc',
data: []
}
}
]
}
})
}, 5000)
}
}
</script>
<style scoped>
</style>
// LoadComs.vue
<script>
import Vue from 'vue'
import myloader from './loadComsVue.js'
export default {
name: 'load-vue',
props: {
comInfo: {
type: Object,
default: () => {
return {}
}
}
},
render(createElement) {
console.log('render::', this.comInfo)
// 这部分是为了渲染父组件本身
let comName = this.comInfo.name
if (!comName) {
return null
}
let com = myloader.loaderVueFile(comName)
let pComponent = com[comName]
if (pComponent && pComponent.default) {
console.log('render~~~', pComponent.default instanceof Vue.component)
Vue.component(comName, pComponent.default)
}
// 这部分是为了把父组件的children渲染做准备,特地分开来写
let childArr = []
let propsChildren = (this.comInfo.props && this.comInfo.props.children) || null
if (Array.isArray(propsChildren) && propsChildren.length > 0) {
propsChildren.forEach(item => {
let childCom = myloader.loaderVueFile(item.name)
let childComponent = childCom[item.name]
if (childComponent && childComponent.default) {
let ccxx = Vue.component(item.name, childComponent.default)
let cc = createElement(item.name, {'props': item.props})
childArr.push(cc)
console.log('ccxx', ccxx)
}
})
}
// context.children = childArr
return createElement(
comName,
{
props: this.comInfo.props
},
[
...childArr
]
)
}
}
</script>
// loadComsVue.js
function loaderVueFile (vueFileName) {
let arr = null
if (typeof vueFileName !== 'string') {
console.error('vue file name is error')
}
return {
[vueFileName]: require('./' + vueFileName)
}
}
export default {
loaderVueFile
}
// 组件库里面的组件
// bg1.vue
<template>
<div class="page">
<p :style="{'background': color}" class="bg1" @click="handleClick">
bg1
</p>
<!-- bg1.vue作为父组件,别忘了加slot -->
<slot></slot>
</div>
</template>
<script>
// @ is an alias to /src
export default {
name: 'bg1',
props: {
color: String
},
created() {
console.log('created...', this.color)
},
mounted() {
console.log('mounted...', this.color)
},
methods: {
handleClick () {
console.log(this.color)
}
}
}
</script>
<style scoped>
.bg1 {
padding: 1em; font-size: 30px; text-align: center; background: #f00eee
}
</style>
网友评论