解决v-html无法理解vue模版的问题-动态获取模版,动态插入app并使用当下app状态数据需求
很多情况下,我们需要使用动态的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状态数据需求的更多相关文章
- 深入理解 Vue 组件
深入理解 Vue 组件 组件使用中的细节点 使用 is 属性,解决组件使用中的bug问题 <!DOCTYPE html> <html lang="en"> ...
- 深刻理解Vue中的组件
转载:https://segmentfault.com/a/1190000010527064 --20更新: Vue2.6已经更新了关于内容插槽和作用域插槽的API和用法,为了不误导大家,我把插槽的内 ...
- VUE.js入门学习(3)-深入理解VUE组建
1.使用组件的细节点 (1)is="模版名" (2)在子组建定义data的时候,data必须是一个函数,而不能是一个对象,每个子组建都有自己的数据存储.之间不会相互影响. (3)操 ...
- 理解vue中的scope的使用
理解vue中的scope的使用 我们都知道vue slot插槽可以传递任何属性或html元素,但是在调用组件的页面中我们可以使用 template scope="props"来获取 ...
- 理解Vue中的Render渲染函数
理解Vue中的Render渲染函数 VUE一般使用template来创建HTML,然后在有的时候,我们需要使用javascript来创建html,这时候我们需要使用render函数.比如如下我想要实现 ...
- 深入理解vue
一 理解vue的核心理念 使用vue会让人感到身心愉悦,它同时具备angular和react的优点,轻量级,api简单,文档齐全,简单强大,麻雀虽小五脏俱全. 倘若用一句话来概括vue,那么我首先想到 ...
- 简单理解Vue中的nextTick
Vue中的nextTick涉及到Vue中DOM的异步更新,感觉很有意思,特意了解了一下.其中关于nextTick的源码涉及到不少知识,很多不太理解,暂且根据自己的一些感悟介绍下nextTick. 一. ...
- vue系列---理解Vue中的computed,watch,methods的区别及源码实现(六)
_ 阅读目录 一. 理解Vue中的computed用法 二:computed 和 methods的区别? 三:Vue中的watch的用法 四:computed的基本原理及源码实现 回到顶部 一. 理解 ...
- 彻底解决eslint与webstorm针对vue的script标签缩进处理方式冲突问题
彻底解决eslint与webstorm针对vue的script标签缩进处理方式冲突问题 2018年12月08日 21:58:26 Kevin395 阅读数 1753 背景不多介绍了,直接上代码. ...
随机推荐
- 【Android】【问题解决记录】Error obtaining UI hierarchy :Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn't exist!
在使用uiautomatorviewer时遇到两类Error obtaining UI hierarchy报错,分别是: Error while obtaining UI hierarchy XML ...
- ThinkPHP获取当前页URL添加canonical
最近ytkah正在开发一个thinkPHP项目,数据量有点大,很多页面都没被索引,需要对模板进行修改,首先需要改的是页面唯一性,因为产品页加入购物车等行为会带有一些参数,如果不加入canonical标 ...
- Tomcat8 访问 manager App 失败
Tomcat8 访问 manager App 失败 进入 tomcat 8 的下面路径 修改 上面 的 context.xml 注释了下面的框框 保存退出.重启tomcat
- 【Js】创建对象的6种方式总结、(底部包含属性名为动态的形式)
一.new 操作符 + Object 创建对象 1 var person = new Object(); 2 person.name = "lisi"; 3 person.age ...
- 在eclipse中打jar包
在Eclipse中打jar包 步骤: 1. 在项目名称中点击右键,点Export... 2.选择java-->Java File, next 3. 选择你打算打包的文件.可以选择某几个文件,也可 ...
- .Net反射在项目中的应用
案例1:项目中可能有多个DAL程序集,每个程序集使用不同的持久化技术或对应不同类型的数据库,但是它们使用同一套接口. 可以在配置文件中配置DAL程序集名称,使用反射加载程序集.创建dal对象. 这样做 ...
- 学习:API断点
API的介绍:API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而 ...
- [PHP] Laravel使用redis保存SESSION
Laravel使用redis保存SESSION 首先确认服务器已经安装redis服务,php安装了redis扩展. 1.打开config/database.php.在redis配置项中增加sessio ...
- C语言博客作业4——数组
0.展示PTA总分 一维数组 二维数组 字符数组 1.本章学习总结 1.1学习内容总结 一维数组知识点: 无论是对一维数组还是二维数组进行应用时,我们对其下标的应用十分广泛. 1:一维数组的输入和遍历 ...
- WebUploader 被 FormData 函数坑了,用了他的页面千万别定FormData变量
WebUploader 被 FormData 函数坑了,用了他的页面千万别定FormData变量 被这个坑了,页面中变量var FormData=null;后又为他赋了值,所有一直上传不了,也没有错 ...