Vue2.0 组件实现动态模板(即Template)

本文介绍了一种利用Vue.js动态生成和插入自定义组件的方法。通过Vue.extend和new Component().$mount(),可以将由Markdown或其他方式生成的HTML模板字符串转换为Vue组件,并手动挂载到DOM中,实现动态内容的展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从 这篇 文章得到启发

先定义一个组件从外部接收Template,然后在组件里调用

<template >
  <div ref="markedContent"></div>
</template>
<script>
import Vue from 'vue/dist/vue.esm.js'
export default {
  name: 'wf-marked-content',
  props: ['content'],
  mounted () {
    this.compile()
  },
  methods: {
    compile () {
      // 变量html是生成好的vue格式的HTML模板字符串,
      // 这个模板里面可以包含各种vue的指令,数据绑定等操作,
      // 比如 v-if, :bind, @click 等。
      const html = this.content
      
      // Vue.extend是vue的组件构造器,专门用来构建自定义组件的,
      // 但是不会注册,类似于js中的createElement,
      // 创建但是不会添加。
      // 在这里创建出一个子组件对象构造器。
      const Component = Vue.extend({
        // 模板文件。由于Markdown解析之后可能会有多个根节点,
        // 因此需要包裹起来。
        // 实际的内容是:
        // `<div><img src="url" @click="showInfo(`图片文字')"></div>`
        template: `<div> ${html} </div>`,
        data() {
          return {
            name: '你'
          }
        },
        // 这里面写的就是这个动态生成的新组件中的方法了,
        // 当然你也可加上data、mounted、updated、watch、computed等等。
        methods: {
          // 上面模板中将点击事件绑定到了这里,因此点击了之后就会调用这个函数。
          // 你可以写多个函数在这里,但是这里的函数的作用域只限在这个子组件中。
          showInfo (title) {
            console.log(title)
          }
        }
      })
      
      // new Component()是将上面构建的组件对象给实例化,
      // $mount()是将实例化的组件进行手动挂载,
      // 将虚拟dom生成出实际渲染的dom,
      // 这里的markedComponent是完成挂载以后的子组件
      const component = new Component().$mount()
      
      // 将挂载以后的子组件dom插入到父组件中
      // markedComponent.$el就是挂载后生成的渲染dom
      this.$refs['markedContent'].appendChild(component.$el)
    }
  }
  // 本质上来讲,这个子组件不是任何组件的子组件,
  // 它是由vue直接在全局动态生成的一个匿名组件,然后将它插入到当前位置的。
  // 也正是因此,它才能够完成动态的生成和添加。
}
</script>

这里尤其要注意 Vue 引入的是 vue.esm.js 这个文件,所以这一句很重要

import Vue from 'vue/dist/vue.esm.js'

不然会报如下错误,大体就是只能用在运行时编译(除非引用的是 vue.esm.js 文件),或根据 这里 的方式修改,都可以实现运行时 template 编译

you are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

下面在父组件中传入template

<template>
  <div id="app">
    <DynamicTemplate content="<div v-text='name'></div>"/>
  </div>
</template>

<script>
import DynamicTemplate from './components/DynamicTemplate.vue'

export default {
  name: 'App',
  components: {
    DynamicTemplate
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

注意这一段

<DynamicTemplate content="<div v-text='name'></div>"/>

只可以使用 v-text 不能使用 {{}},不然也会编译报错。实际效果如下

这个"你"字就是我在子组件定义的 name 的值 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值