解决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是一个非常不错的选择!~
相关文章
- 一步一步教你用 Vue.js + Vuex 制作专门收藏微信公众号的 app
- APP测试工程师岗位面试题
- 面试百问:如何测试App性能?
- 报错:ls: 无法访问/opt/app/spark/lib/spark-assembly-*.jar: 没有那个文件或目录
- uni-app - vue以及微信小程序
- 【Anroid界面实现】WindowManager类使用具体解释——用户首次打开APP的使用教学蒙板效果实现
- Google Earth Engine APP(GEE) ——创建一个连续的图例
- Vue - PC 端列表下拉页面触底加载分页数据,监听浏览器屏幕触底事件,类似uni-app微信小程序的onReachBottom()页面触底生命周期函数(监听屏幕触底事件,实现懒加载效果)
- Vue - 搜索关键字标红高亮(用户输入关键词搜索后,在搜索结果的列表标题上匹配并标红加粗)怎么使内容文本标红高亮的最详细教程,Nuxt.js uni-app 也适用,搜索功能及搜索结果关键字高亮源码
- 面点:手机APP测试都要注意哪些问题?
- [转]UNI-APP开发笔记之使用uni.navigateBack修改上一个页面值
- Android Activity交互及App交互
- Vue.js高仿饿了么外卖App学习记录
- 从零开始学android开发-adt-bundle-eclipse下的修改android app名称
- 【AGC】增长服务3-App Linking示例
- 《移动App测试的22条军规》—App测试综合案例分析23.14节测试微信App的增量升级
- 基于XCode IOS开发系统实现的新闻APP【100010688】
- Cordova+Vue快速搭建Hybrid App
- SwiftUI 前后端完整项目大全 之 网上商店App基于Node.js、Express和Vue构建 (项目含源码)
- SwiftUI 运动类完整项目之 自行车运动App具有实时路线跟踪、实时指标、过去自行车路线coredata(项目含源码)
- Java_关于App class loader的总结
- 从打击App刷榜看苹果的底线
- 每一个开发人员都应该有一款自己的App