Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 422|回复: 0

解决v-html无法理解vue模版的问题-动态获取模版,动态插入app并使用当下app状态数据需求

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-5-1 12:11:51 | 显示全部楼层 |阅读模式

    很多情况下,我们需要使用动态的html作为某个dom元素的inner html,如果这个内容是标准的html的话,则v-html能够圆满满足需求,而如果内容包含了vue组件,则使用v-html就不能达到你希望的目标了。

    我研究有两种方案来解决,一种原生使用v-if提供的compile和mount特性;第二种类则使用render函数带来的特殊能力实现这一点。

    其中render函数的方案有一个现成的vue组件作为参考. v-runtime-template.

    该组件产生的背景:

    在项目开发中需要从server上接收template string.比如,即允许用户自己通过拖拽来设计接口风格的程序中,通常被保存为vue template code,而该code会使用由前端工程师开发好的预定义组件。这些组件将通过api调用请求数据并且填充页面的一个部分。

    正如上面所说的,v-html很大程度上能够部分满足需求:

    <template>
      <div>
        <div v-html="template"></div>
      </div>
    </template>
    
    <script>
    export default {
      data: () => ({
        template: `
          <h2>Howdy Yo!</h2>
          <a href="croco-fantasy">Go to the croco-fantasy</a>
        `
      }),
    };
    </script>

    上面的template字符串可以从server ajax call中获得。问题是,如果该template string中包含了vue template code,则无能为力!

    export default {
      data: () => ({
        template: `
          <app-title>Howdy Yo!</app-title>
          <vue-router to="/croco-fantasy">Go to the croco-fantasy</vue-router>
        `
      }),
    };

    v-html并不能理解vue-router这个tag,因此将会丢弃很多重要功能。

    这时作者就需要开发一个能够解决该类问题的"proxy"组件

    v-runtime-template的实现原理是: 自动获得v-runtime-template的父组件的context并且使得vue编译并且attach.

    render(h) {
        if (this.template) {
          const parent = this.parent || this.$parent
          const {
            $data: parentData = {},
            $props: parentProps = {},
            $options: parentOptions = {}
          } = parent;
          const {
            components: parentComponents = {},
            computed: parentComputed = {},
            methods: parentMethods = {}
          } = parentOptions;
          const {
            $data = {},
            $props = {},
            $options: { methods = {}, computed = {}, components = {} } = {}
          } = this;
          const passthrough = {
            $data: {},
            $props: {},
            $options: {},
            components: {},
            computed: {},
            methods: {}
          };
    
          //build new objects by removing keys if already exists (e.g. created by mixins)
          Object.keys(parentData).forEach(e => {
            if (typeof $data[e] === "undefined")
              passthrough.$data[e] = parentData[e];
          });
          Object.keys(parentProps).forEach(e => {
            if (typeof $props[e] === "undefined")
              passthrough.$props[e] = parentProps[e];
          });
          Object.keys(parentMethods).forEach(e => {
            if (typeof methods[e] === "undefined")
              passthrough.methods[e] = parentMethods[e];
          });
          Object.keys(parentComputed).forEach(e => {
            if (typeof computed[e] === "undefined")
              passthrough.computed[e] = parentComputed[e];
          });
          Object.keys(parentComponents).forEach(e => {
            if (typeof components[e] === "undefined")
              passthrough.components[e] = parentComponents[e];
          });
    
          const methodKeys = Object.keys(passthrough.methods || {});
          const dataKeys = Object.keys(passthrough.$data || {});
          const propKeys = Object.keys(passthrough.$props || {});
          const templatePropKeys = Object.keys(this.templateProps);
          const allKeys = dataKeys.concat(propKeys).concat(methodKeys).concat(templatePropKeys);
          const methodsFromProps = buildFromProps(parent, methodKeys);
          const finalProps = merge([
            passthrough.$data,
            passthrough.$props,
            methodsFromProps,
            this.templateProps
          ]);
          const provide = this.$parent._provided;
    
          const dynamic = {
            template: this.template || "<div></div>",
            props: allKeys,
            computed: passthrough.computed,
            components: passthrough.components,
            provide: provide
          };
    
          return h(dynamic, { props: finalProps });
        }
      }

    以上代码就是v-runtime-template的核心render函数.

    <template>
      <div>
        <v-runtime-template :template="template"/>
      </div>
    </template>
    
    <script>
    import VRuntimeTemplate from "v-runtime-template";
    import AppTitle from "./AppTitle";
    
    export default {
      data: () => ({
        template: `
          <app-title>Howdy Yo!</app-title>
          <vue-router to="/croco-fantasy">Go to the croco-fantasy</vue-router>
        `
      }),
    components: {
        AppTitle
      }
    };
    </script>

    上面就是使用v-runtime-template核心用法代码。有一点需要额外指出的是,它还可以访问父组件的scope,意味着任何通过data,props,computed或者methods能够访问的都能用.这样你就可以拥有dynaimc templates的能力:可被父组件访问的活跃reactive数据.

    比如:

    export default {
      data: () => ({
        animal: "Crocodile",
        template: `
          <app-title>Howdy {{animal}}!</app-title>
          <button @click="goToCrocoland">Go to crocoland</button>
        `
      }),
      methods: {
        goToCrocoland() {
          // ...
        }
      }

    如果你需要动态地应用从server端返回的template,并能插入vue app中获得对应的scope context访问能力,那么v-runtime-template是一个非常不错的选择!~

    https://alligator.io/vuejs/v-runtime-template/

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-19 02:01 , Processed in 0.072114 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表