很多情况下,我们需要使用动态的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/

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

  1. 深入理解 Vue 组件

    深入理解 Vue 组件 组件使用中的细节点 使用 is 属性,解决组件使用中的bug问题 <!DOCTYPE html> <html lang="en"> ...

  2. 深刻理解Vue中的组件

    转载:https://segmentfault.com/a/1190000010527064 --20更新: Vue2.6已经更新了关于内容插槽和作用域插槽的API和用法,为了不误导大家,我把插槽的内 ...

  3. VUE.js入门学习(3)-深入理解VUE组建

    1.使用组件的细节点 (1)is="模版名" (2)在子组建定义data的时候,data必须是一个函数,而不能是一个对象,每个子组建都有自己的数据存储.之间不会相互影响. (3)操 ...

  4. 理解vue中的scope的使用

    理解vue中的scope的使用 我们都知道vue slot插槽可以传递任何属性或html元素,但是在调用组件的页面中我们可以使用 template scope="props"来获取 ...

  5. 理解Vue中的Render渲染函数

    理解Vue中的Render渲染函数 VUE一般使用template来创建HTML,然后在有的时候,我们需要使用javascript来创建html,这时候我们需要使用render函数.比如如下我想要实现 ...

  6. 深入理解vue

    一 理解vue的核心理念 使用vue会让人感到身心愉悦,它同时具备angular和react的优点,轻量级,api简单,文档齐全,简单强大,麻雀虽小五脏俱全. 倘若用一句话来概括vue,那么我首先想到 ...

  7. 简单理解Vue中的nextTick

    Vue中的nextTick涉及到Vue中DOM的异步更新,感觉很有意思,特意了解了一下.其中关于nextTick的源码涉及到不少知识,很多不太理解,暂且根据自己的一些感悟介绍下nextTick. 一. ...

  8. vue系列---理解Vue中的computed,watch,methods的区别及源码实现(六)

    _ 阅读目录 一. 理解Vue中的computed用法 二:computed 和 methods的区别? 三:Vue中的watch的用法 四:computed的基本原理及源码实现 回到顶部 一. 理解 ...

  9. 彻底解决eslint与webstorm针对vue的script标签缩进处理方式冲突问题

    彻底解决eslint与webstorm针对vue的script标签缩进处理方式冲突问题 2018年12月08日 21:58:26 Kevin395 阅读数 1753   背景不多介绍了,直接上代码. ...

随机推荐

  1. Linux操作系统的打包/归档工具介绍

    Linux操作系统的打包/归档工具介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  2. 重新编译kubeadm,修改默认证书时间

    参考 kubeadm alpha certs renew Kubeadm1.14 证书调整 kubeadm 部署的 kubernetes 集群,默认的证书有效时间是1年,需要每年手工更新. 1. 重新 ...

  3. [转]【HttpServlet】HttpServletResponse接口 案例:完成文件下载

    创建时间:6.19 & 6.24 1.案例-完成文件下载 1)  什么情况下会文件下载? 浏览器不能解析的文件就下载 *使用a标签直接指向服务器上的资源 2)什么情况下需要在服务端编写文件下载 ...

  4. 一探istio-proxy(envoy)容器里的秘密

    今天,在测试环境跑通了istio. 惭愧,是用MicroK8s跑的,其它环境,不敢呀. 基本功能都OK了. 在运行了istio-injection=enabled之后,每个pod运行时,会多一个ist ...

  5. 关于python切片操作笔记

    一. Python可切片对象的索引方式 包括:正索引和负索引两部分,如下图所示,以a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]为例:   python索引方式.jpg 二. P ...

  6. chromedriver对应chrome版本

    chromedriver版本 支持的Chrome版本 v2.41 v67-69 v2.40 v66-68 v2.39 v66-68 v2.38 v65-67 v2.37 v64-66 v2.36 v6 ...

  7. Django 购物车模板

    url from django.contrib import admin from django.urls import path, re_path from django.urls import i ...

  8. MySQL中 ORDER BY 与 LIMIT 的执行顺序

    如下: ORDER BY 与 LIMIT 的执行顺序:ORDER BY > LIMIT ORDER BY 与 LIMIT 的编写顺序:ORDER BY > LIMIT 正确写法: sele ...

  9. django -- 模版语言之过滤器Filters和for循环

    前戏 在前面写的图书管理系统中,我们对模版语言应该已经不陌生了,使用{{ }}包裹起来的就是模版语言,只需要记住两种就可以了 {{ 变量名 }}            变量相关的 {% %}      ...

  10. 10-排序5 PAT Judge (25 分)

    The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...