编译在运行时作为 prop 接收的 Vuetify 标签/模板

我想向组件发送一个“模板”道具然后渲染它。如果我发送一个纯 HTML 它可以工作,但是如果我发送一个 Vuetify 标签,比如<v-btn>test</v-btn>模板不会被编译。


我知道我不应该通过道具传递模板,但这是一个特殊情况:父组件充当“模板构建器”,子组件充当“结果查看器”,所以我必须将创建的模板传递给孩子,以便它可以编译并显示它。


这是我一直在尝试的:


主程序


import Vue from 'vue'

import App from './App.vue'

// Some imports here ...

import vuetify from './plugins/vuetify';


new Vue({

    vuetify,

    render: h => h(App)

}).$mount('#app')

应用程序.vue


<script


import Vue from 'vue'


// eslint-disable-next-line

var staticRenderFns = [];


var dynamic = {

  props: ['template'],

  data: () => ({

      templateRender: null,

  }),

  render(h) {

    if (!this.templateRender) {

      return h('div', 'loading...');

    } else { // If there is a template, I'll show it

      return this.templateRender();

    }

  },

  watch: {

    // Every time the template prop changes, I recompile it to update the DOM

    template:{

      immediate: true, // makes the watcher fire on first render, too.

      handler() {

        var res = Vue.compile(this.template);


        this.templateRender = res.render;

        

        // staticRenderFns belong into $options, 

        // appearantly

        this.$options.staticRenderFns = []

        

        // clean the cache of static elements

        // this is a cache with the results from the staticRenderFns

        this._staticTrees = []

        

        // Fill it with the new staticRenderFns

        for (var i in res.staticRenderFns) {

          //staticRenderFns.push(res.staticRenderFns[i]);

          this.$options.staticRenderFns.push(res.staticRenderFns[i])

        }

      }

    }

  },

}


export default {

  name: 'App',

  data: () => ({

    template:`

            <v-row>

              <v-col>

                <v-btn class="pa-2 primary white--text">Test</v-btn>

              </v-col>

              <v-col>

                <v-btn class="pa-2 primary white--text">Test</v-btn>

              </v-col>

              <v-col>

                <v-btn class="pa-2 primary white--text">Test</v-btn>

              </v-col>

            </v-row>

    `,

  }),

  components:{

    dynamic,

  },



温温酱
浏览 117回答 1
1回答

FFIVE

在动态组件内部尝试使用传递的模板渲染一个 vue 组件:var dynamic = {&nbsp; props: ['template'],&nbsp; data: () => ({&nbsp; &nbsp; &nbsp; templateRender: null,&nbsp; }),&nbsp; render(h) {&nbsp; &nbsp; if (!this.template) {&nbsp; &nbsp; &nbsp; return h('div', 'loading...');&nbsp; &nbsp; } else { // If there is a template, I'll show it&nbsp; &nbsp; &nbsp; return h(Vue.component('dynamic-render', {template:this.template}));&nbsp; &nbsp; }&nbsp; },}完整示例var dynamic = {&nbsp; props: ['template'],&nbsp; data: () => ({&nbsp; &nbsp; templateRender: null,&nbsp; }),&nbsp; render(h) {&nbsp; &nbsp; if (!this.template) {&nbsp; &nbsp; &nbsp; return h('div', 'loading...');&nbsp; &nbsp; } else { // If there is a template, I'll show it&nbsp; &nbsp; &nbsp; return h(Vue.component('dynamic-render', {&nbsp; &nbsp; &nbsp; &nbsp; template: this.template&nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }&nbsp; },}var app = new Vue({&nbsp; el: '#app',&nbsp; vuetify: new Vuetify(),&nbsp; data: () => ({&nbsp; &nbsp; count: 1,&nbsp; &nbsp; template: `&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-row>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-col>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-btn class="pa-2 primary white--text">Test</v-btn>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </v-col>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-col>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-btn class="pa-2 primary white--text">Test</v-btn>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </v-col>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-col>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-btn class="pa-2 primary white--text">Test</v-btn>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </v-col>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </v-row>&nbsp; &nbsp; `,&nbsp; }),&nbsp; components: {&nbsp; &nbsp; dynamic,&nbsp; },&nbsp; methods: {&nbsp; &nbsp; changeContent() {&nbsp; &nbsp; &nbsp; this.count = this.count + 1&nbsp; &nbsp; &nbsp; this.template = '';&nbsp; &nbsp; &nbsp; setTimeout(() => { //simulate loading status&nbsp; &nbsp; &nbsp; &nbsp; this.template = `<v-col>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <v-btn class="pa-2 primary white--text">Btn ${this.count}</v-btn>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </v-col>`&nbsp; &nbsp; &nbsp; }, 2000);&nbsp; &nbsp; }&nbsp; }})<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"><script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script><script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script><script src="https://unpkg.com/axios/dist/axios.min.js"></script><div id="app">&nbsp; <v-app id="inspire">&nbsp; &nbsp; <v-btn depressed color="primary" class="black--text" @click="changeContent">change content</v-btn>&nbsp; &nbsp; <dynamic :template='template'></dynamic>&nbsp; </v-app></div>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript