很多情况下,我们需要使用动态的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. Nginx应用详解及配置

    一.Nginx简介 概述:Nginx是一款由俄罗斯开发的开源的高性能HTTP服务器和反向代理服务器,同时支持IMAP/POP3/SMTP代理服务,其性能优势着为显著,官网上称:单台nginx服务器可以 ...

  2. Natas25-writeup

    前言 题目链接: http://natas25.natas.labs.overthewire.org 做这一题花了一些时间,也是由于自己知识点掌握不足,所以分享下解题过程. 题目分析 首先,登录后看到 ...

  3. dgango

    一 mvc与mtv模型 web服务器开发领域里著名的mvc模式,所谓mvc就是把web应用分为模型(M),控制器(C),视图(V),以插件的形式,松耦合的方式连接在一起,模型负责业务对象与数据库的映射 ...

  4. 201871010131-张兴盼《面向对象程序设计(java)》第二周学习总结

    项目 内容 <面向对象程序设计(java)> https://home.cnblogs.com/u/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.c ...

  5. mysql5.6采集数据插入出现MySQL server has gone away解决办法

    当做网站有一个站要用到WEB网页采集器功能,当一个PHP脚本在请求URL的时候,可能这个被请求的网页非常慢慢,超过了mysql的 wait-timeout时间,然后当网页内容被抓回来后,准备插入到My ...

  6. hbase表的高性能设计

    第7章 HBase优化 7.1 高可用 在HBase中Hmaster负责监控RegionServer的生命周期,均衡RegionServer的负载,如果Hmaster挂掉了,那么整个HBase集群将陷 ...

  7. NOIP 2013 火柴排队

    洛谷 P1966 火柴排队 洛谷传送门 JDOJ 2227: [NOIP2013]火柴排队 D1 T2 JDOJ传送门 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高 ...

  8. ABP 依赖报错

    一般是自己写的Service 没有实现IApplicationService,和没有继承ApplicationService

  9. Spring Boot 知识笔记(整合Mybatis续-补充增删改查)

    续上篇,补充数据库增删改查的其他场景. 一.Mapper中添加其他场景操作 package net.Eleven.demo.Mapper; import net.Eleven.demo.domain. ...

  10. 【BigData】Java基础_HashSet

    HashSet简介 HashSet是一个集合数据类型,具有以下三个特性: (1)可以存储过个数据对象 (2)HashSet中的数据不能重复 (3)HashSet的数据存储是无序的 HashSet的几个 ...