今天在项目开发中,遇到从后端返回的vue文件(包含template,js,css)的文件,试过用v-html解析文件,渲染到页面,但是无法渲染,后来去查了一堆资料,自己写了一个全局方法来解析这类文件

1,在项目目录新建一个mixin文件,再创建一个strToVueFormMixin.js文件,文件内容为:

import {
invokeServiceWait,
checkRequestStatus,
handleCallbackFn,
} from "@/InitMethods/formHttp";
export default {
data() {
return {
_form: null,
isStartLoad: false,
};
},
methods: {
/**
* 替换元素的style font-size
*/
replaceStyleFontSize(templateStr){
let fontSize = localStorage.getItem('fontSizeMultiplier');
// 存在获取fontSizeMultiplier为null时 默认字体放大倍数取1
fontSize==null?fontSize=1:fontSize;
if(fontSize){
let fontSizeExp= /(\s?font-size:\s?)([0-9.]+)([a-zA-Z]*)/g //let fontSizeExp = /(\s?font-size:\s?)([0-9.]+)([a-zA-Z]*[\s|;|}|\)])/g;
templateStr= templateStr.replace(fontSizeExp,(match, key, n, unit) => {
console.log(match)
return key + Number(n) * fontSize + unit;
})
return templateStr
} },
/**
* 服务器表单字符串转化Vue表单挂在到对应DOM节点
*
* @param {String} formStr VueFrom文件的字符串
* @param {String} queryStr Vue实例需要挂在DOM节点的id或者class
*
*/
strToVueForm(formStr, queryStr) {
if (typeof formStr == "string" && formStr.length) {
// 检查id是否存在
if (!document.querySelector(`${queryStr}`)) {
console.error('"id" or "class" does not exist!');
return {};
}
let fromStyleDom = null;
let styleBegin = 0; // style截取开始位置
let styleEnd = 0; // style截取结束位置
let templateBegin = 0; // template截取开始位置
let templateEnd = 0; // template截取结束位置
let scriptBegin = 0; // script截取开始位置
let scriptEnd = 0; // script截取结束位置 // 解析Vue字符串文件中的样式并添加到app全局中
if (formStr.indexOf("<style") > -1) {
styleBegin = formStr.indexOf("<style") + "<style".length;
styleEnd = formStr.indexOf("</style>");
let styleStr = formStr.substring(styleBegin, styleEnd);
// 再次去除stlye中的属性设置(例如:lang="sass" scoped)
let styleStartIndex = styleStr.indexOf(">") + 1;
styleStr = styleStr.substring(styleStartIndex);
// 添加到全局样式中
if (styleStr) {
fromStyleDom = document.createElement("style");
fromStyleDom.innerHTML = styleStr;
// style样式插入header中
document.head.appendChild(fromStyleDom);
}
} // 解析Vue字符串模板中的template以及script并挂到对应的dom节点
templateBegin = formStr.indexOf("<template>") + "<template>".length;
templateEnd = formStr.lastIndexOf("</template>");
let templateStr = formStr.substring(templateBegin, templateEnd);
templateStr = templateStr
.replace(/\r\n/g, " ")
.replace(/\n/g, " ")
.replace(/"/g, '\\"');
console.log("templateStr前",templateStr)
templateStr=this.replaceStyleFontSize(templateStr)
console.log("templateStr后",templateStr)
templateStr = 'let formtemplate ="' + templateStr + '";\n';
scriptBegin = formStr.indexOf("<script>") + "<script>".length;
scriptEnd = formStr.indexOf("</script>");
let scriptStr = formStr.substring(scriptBegin, scriptEnd);
// 防止window.vue.extend之前还定义了变量导致Cusform赋值无法得到window.vue.extend
if (scriptStr.indexOf(window.vue.extend) != 0) {
scriptStr = scriptStr.replace(
/window.vue.extend/,
"var Cusform = window.vue.extend"
);
} else {
scriptStr = "let Cusform =" + scriptStr;
}
let insetIndex =
scriptStr.indexOf("window.vue.extend({") +
"window.vue.extend({".length;
// 添加beforeDestroy
let destroyMixinStr = `
mixins:[{
beforeDestroy: function() {
fromStyleDom && fromStyleDom.remove()
}
}],`;
scriptStr =
scriptStr.slice(0, insetIndex) +
destroyMixinStr +
scriptStr.slice(insetIndex);
// console.log("scriptStr:", scriptStr);
let Cusform = eval(templateStr + scriptStr + ";" + "Cusform");
this.isStartLoad = false;
Cusform.prototype.invokeServiceWait = invokeServiceWait;
Cusform.prototype.isStartLoad = false;
Cusform.prototype.checkRequestStatus = function () {
return checkRequestStatus(this.isStartLoad);
}; let vueForm = new Cusform().$mount(`${queryStr}`); this._form = vueForm;
vueForm.isStartLoad = true;
this.isStartLoad = true; return vueForm;
} else {
return {};
}
},
},
beforeDestroy() {
this._form && this._form.$destroy();
},
};

2,如何使用:

在新建文件是要用到mixin时,我们只要引入就可以使用了

新建MyPaidLeaveInfo.js文件:

import strToVueFormMixin from '@/mixins/strToVueFormMixin';
export default {
mixins: [strToVueFormMixin],
name: 'PaidLeaveInfoPC',
data() {
return {
fileStr:'',
myForm:{},
formLoadStatus: null,
}
},
mounted() {
this.init();
},
methods: {
// 获取PaidLeaveInfoPC表单
getFile() {
return new Promise((resolve, reject) => {
this.invokeService(
'AnnualLeave',
'GetCustomForm',
['PaidLeaveInfoPC'],
msg => {
const $ = msg.ReturnData.$;
if ($.Succeed) {
const fileStr = Lark.base64Decode($.Data);
this.fileStr = fileStr;
resolve(fileStr);
} else {
reject();
}
},
err => {
reject(err);
}
);
});
},
init() {
this.formLoadStatus = new Promise((resolve, reject) => {
this.getFile()
.then(file => this.fileToHtml(file))
.then(() => {
resolve();
})
.catch(err => {
console.log(err,'err');
reject();
});
});
},
// 后端返回的数据转为vhtml
fileToHtml(file) {
file = file.replace(/wfm-popup/g, 'paidleaveinfoPC-popup');
let vueForm = this.strToVueForm(file, '#paidLeaveInfoPC');
this.myForm = vueForm;
return Promise.resolve();
}
}
}

新建MyPaidLeaveInfo.vue文件

只需要定义一个容器包住就可以了

<template>
<el-row>
<el-header style="height: 30px" class="wfm-first-header"
><WFMBreadcrumb></WFMBreadcrumb
></el-header>
<div id="paidLeaveInfoPC"></div>
</el-row>
</template> <script>
import MyPaidLeaveInfoJS from './MyPaidLeaveInfo.js';
export default MyPaidLeaveInfoJS;
</script> <style lang="scss" scoped>
@import './MyPaidLeaveInfo.scss';
</style>

服务器表单字符串转化Vue表单挂在到对应DOM节点的更多相关文章

  1. React 事件对象、键盘事件、表单事件、ref获取dom节点、react实现类似Vue双向数据绑定

    1.案例实现代码 import React, { Component } from 'react'; /** * 事件对象.键盘事件.表单事件.ref获取dom节点.react实现类似Vue双向数据绑 ...

  2. vue 钩子函数中获取不到DOM节点

    原文链接:https://jingyan.baidu.com/article/f96699bbfe9c9d894f3c1b4b.html 两种解决方案: 1:官方解决方案: 受到 HTML 本身的一些 ...

  3. vue,在模块中动态添加dom节点,并监听

    在这里,onclick事件没有作用,因为它指向的是window,如果写为this.click页面显示为undefined, 我采用的是通过class绑定事件,但是会有一个问题,那就是当你渲染多个事件时 ...

  4. 六、React 键盘事件 表单事件 事件对象以及React中的ref获取dom节点 、React实现类似Vue的双向数据绑定

    接:https://www.cnblogs.com/chenxi188/p/11782349.html 事件对象 .键盘事件. 表单事件 .ref获取dom节点.React实现类似vue双向数据绑定 ...

  5. 第四节:Vue表单标签和组件的基本用法,父子组件间的通信

    vue表单标签和组件的基本用法,父子组件间的通信,直接看例子吧. <!DOCTYPE html> <html> <head> <meta charset=&q ...

  6. Vue表单

    gitHub地址: https://github.com/lily1010/vue_learn/tree/master/lesson11 一 vue表单 实在是太简单了,直接来个例子 <!DOC ...

  7. Vue表单控件绑定

    前面的话 本文将详细介绍Vue表单控件绑定 基础用法 可以用 v-model 指令在表单控件元素上创建双向数据绑定.它会根据控件类型自动选取正确的方法来更新元素.v-model本质上不过是语法糖,它负 ...

  8. Vue表单绑定(单选按钮,选择框(单选时,多选时,用 v-for 渲染的动态选项)

    <!DOCTYPE html><html>    <head>        <meta charset="utf-8">      ...

  9. vue 表单校验(二)

    vue 表单校验(二) vue element-ui表单校验 由于现在使用element-ui进行form表单校验,因而使用其自带的校验规则进行校验,发现有些并不是那么好校验,或者说是校验起来很繁琐, ...

随机推荐

  1. [BUUCTF]PWN7——[OGeek2019]babyrop

    [BUUCTF]PWN7--[OGeek2019]babyrop 题目网址:https://buuoj.cn/challenges#[OGeek2019]babyrop 步骤: 例行检查,32位,开启 ...

  2. 拆分行(Power Query 之 M 语言)

    数据源: 略 目标: 将指定列拆分为行 操作过程: 选取指定列>[主页](或[转换])>[拆分列]>[按分隔符]/[按字符数]/[按位置]>高级选项>拆分为[行] M公式 ...

  3. 资源分配情况(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 资源的分配情况,无非就是未分配.已分配和过度分配三种,这些都可以通过各种视图查看,比如[资源]>[工作组规划器]视图 ...

  4. 区块链开发学习第七章:第一个Dapp-猜拳游戏

    第一个简单的Dapp-猜拳游戏.本智能合约的功能很简单,就是用户与电脑猜拳,用户选择出手后,电脑随机一个选项,然后调用智能合约方法把两个选项值传过去,在智能合约上进行比较,并通过区块链合约事件广播结果 ...

  5. AT4811 [ABC160D] Line++ 题解

    Content 给定一个 \(n\) 个点.\(n\) 条边的无向图.对于所有的 \(1\leqslant i<n\),在点 \(i,i+1\) 之间连一条无向边.另外在给定两个点 \(x,y\ ...

  6. Asp.Net Core基础篇之:白话管道中间件

    在Asp.Net Core中,管道往往伴随着请求一起出现.客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行. 举一个生活中比较常见的例子:旅游景区. 我们都知道,有些景区大门离景 ...

  7. 宕机导致分区丢失恢复方案testdisk

    一.执行此预案的动机 云主机数据盘分区丢失 二.执行此预案的条件 1.确定用户在报障时间点之前有过数据盘分区存在,而在报障时间点该分区消失 2.在执行我们的恢复操作之前,确保将分区所在数据盘进行备份 ...

  8. SpringBoot基础篇(一)

    1.前言 什么是SpringBoot:springboot是当下一套流行的J2EE框架.借助微服务的思想.将业务分成一个个的服务.通过spring-cloud进行整合.最后通过spring-data进 ...

  9. SpringBoot 封装异步执行任务简单demo

    ThreadPoolConfig.java import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.concurrent.B ...

  10. 刷完 900 多题后的首次总结:LeetCode 应该怎么刷?

    「负雪明烛」公众号是负雪明烛维护的一个算法题解公众号,致力于帮助大家刷题.找工作.欢迎关注. 大家好,我是负雪明烛.今天跟大家聊一聊「LeetCode应该怎么刷?」这个话题. 我是大二的时候开始接触 ...