vue3 将字符串组件转为vnode 进行渲染

近期不忙,想着使用vue3 将字符串模板进行渲染并显示组件。如下代码

let htmlStr=`<script>
      export default{
        setup(){
        },
        data(){
            return{
              a:'xxxxxxxxxxxxx',
              arr:[1,2,3,4,5,6,7,8,9,10],
              showmodal:false,
            }
          },
          mounted(){
           
          //  console.log(this)
          //  console.log(message)
            
          },
          methods:{
            testmethods(){
              // this.message.info('testmethods')
            }
          }
      }
<\/script>
<template>
 <div>111111111111</div>
 <div v-if='showmodal'>showmodal</div>
 <p><b>{{a}}</b></p>
 <h3 v-for='arrItem,key in arr'>{{arrItem}}{{key}}</h3>
 <button type='primary' @click='testmethods'>ant按钮</button>
 <button type='primary' @click='showmodal=true'>modal</button>
 <button class='ant-btn' >啊撒旦范德萨分</button>
</template>
<style>
  h3{color:red}
</style>
    `

计划上面的内容是通过后台接口获取,并根据返回内容挂载到项目中使用,

这样再以后做新项目时候,ctrl+C ctrl+v 后直接改下取数据的接口,改下逻辑新项目就可以直接使用了,网上看了很多教程,但是感觉复杂而且不够灵活,先把思路整理记录下 。

使用的的组件 @vue/compiler-sfc ,涉及到的Vue 的 函数有 crateVnode 或者 h 或者 createAPP,这三个都可以 。

话不多说第一步把字符串解析为Vue 可以使用的文件。Vue 组件 构成 三大块  template script style

@vue/compiler-sfc 的parse方法是将 字符串解析为  vue的三个部分,代码为非运行代码,最后会有全量代码,引入安装@vue/compiler-sfc 

1.命令  npm install  @vue/compiler-sfc ,安装完毕后import parse 如下

import { parse } from "@vue/compiler-sfc";
 const parseObj = parse(htmlStr)

小伙伴可以通过console.log 打印看看 parseObj 的输出部分

2. 解析出 template script styles

 const { script,scriptSetup, template, styles } = parseObj.descriptor;
        let curentScript = (script || scriptSetup)?.content
        const fhtml = curentScript && curentScript.replace(/export\s+default/,"")
        const runScript  = eval(`(${ fhtml })`)
        runScript.template = template?.content

3.将解析的代码使用 createVnode 输出

const vnode = h({...runScript});
        
       
        render(vnode,document.getElementById('vcode'))

至此渲染完成,不过存在的问题是 组件库 的 样式 没有正常显示,我使用的antd组件库 ,这里需要单独注册组件,有点儿麻烦,我这里抛砖引玉下,有高手可以分享下看看如何解决组件引入的问题

完整代码如下

<template>
    <a-button @click="loadCmp">加载组件</a-button>
    <div id="vcode">view code</div>
    <!-- <CustomCmp/> -->
 
</template>
<script setup lang="ts">
import { createApp, createVNode, getCurrentInstance, h, isVNode, nextTick,  onMounted,  ref,  render, VNodeChild } from 'vue';
import { parse } from "@vue/compiler-sfc";
import { message,Button } from 'ant-design-vue';
import Test from './test.vue';
import Antd from 'ant-design-vue';
import zhCh from 'ant-design-vue/es/locale/zh_CN'
import '../../../assets/css/comm.css'

const loadCmp = ()=>{
  renderCode()
}

let cpmRef = ref('')

  const  renderCode = ()=> {
      let htmlStr=`<script>
      export default{
        setup(){
        },
        data(){
            return{
              a:'xxxxxxxxxxxxx',
              arr:[1,2,3,4,5,6,7,8,9,10],
              showmodal:false,
            }
          },
          mounted(){
           
          //  console.log(this)
          //  console.log(message)
            
          },
          methods:{
            testmethods(){
              // this.message.info('testmethods')
            }
          }
      }
<\/script>
<template>
 <div>111111111111</div>
 <div v-if='showmodal'>showmodal</div>
 <p><b>{{a}}</b></p>
 <h3 v-for='arrItem,key in arr'>{{arrItem}}{{key}}</h3>
 <button type='primary' @click='testmethods'>ant按钮</button>
 <button type='primary' @click='showmodal=true'>modal</button>
 <button class='ant-btn' >啊撒旦范德萨分</button>
</template>
<style>
  h3{color:red}
</style>
    `
        const parseObj = parse(htmlStr)
        const { script,scriptSetup, template, styles } = parseObj.descriptor;
        let curentScript = (script || scriptSetup)?.content
        const fhtml = curentScript && curentScript.replace(/export\s+default/,"")
        const runScript  = eval(`(${ fhtml })`)
        runScript.template = template?.content
        const vnode = h({...runScript});
        
       
        render(vnode,document.getElementById('vcode'))

        // cpmRef.value = vnode

       

    }
    


  
</script>

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值