今天在项目开发中,遇到从后端返回的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. 项目的基本概念(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 我一看到这个标题就头疼,好吧,又是概念,好在我不要参加相关的考试,否则文字连同标点符号都得背%¥#%#~ 张同学说,项目& ...

  2. 「Python实用秘技03」导出项目的极简环境依赖

    本文完整示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/PythonPracticalSkills 这是我的系列文章「Python实用秘技」的第3期 ...

  3. 小迪安全 Web安全 基础入门 - 第二天 - Web应用&架构搭建&漏洞&HTTP数据包&代理服务器

    一.网站搭建 1.域名.是由一串用点分隔的字符组成的互联网上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位.域名可以说是一个IP地址的代称,目的是为了便于记忆后者. 2.子域名.在 ...

  4. .NET 云原生架构师训练营(建立系统观)--学习笔记

    目录 目标 ASP .NET Core 什么是系统 什么是系统思维 系统分解 什么是复杂系统 作业 目标 通过整体定义去认识系统 通过分解去简化对系统的认识 ASP .NET Core ASP .NE ...

  5. Git的基本使用(只是基本使用)

    git上传 1.克隆到本地 git clone + git项目地址 2.添加文件 git add * 添加所有文件到本地仓库 3.查看状态 git status 4.标记 git commit -m ...

  6. TensorFlow.NET机器学习入门【1】开发环境与类型简介

    项目开发环境为Visual Studio 2019 + .Net 5 创建新项目后首先通过Nuget引入相关包: SciSharp.TensorFlow.Redist是Google提供的TensorF ...

  7. CF1581B Diameter of Graph 题解

    Content \(\textsf{CQXYM}\) 想要构造一个包含 \(n\) 个点和 \(m\) 条边的无向连通图,并且他希望这个图满足下列条件: 该图中不存在重边和自环.也就是说,一条边应该连 ...

  8. 使用yml简化多行sql语句案例

    task:sql:# 将某个值插入到报表- insert into report_app_detail(curr_date,key_name,key_value) values(:curr_date, ...

  9. 【剑指Offer】52. 两个链表的第一个公共节点 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 方法一:栈 方法二:HashSet 方法三:不使用额外空间 日期 ...

  10. [LeetCode]621. Task Scheduler 任务安排 题解

    题目描述 给定一个char数组,代表CPU需要做的任务,包含A-Z,不用考虑顺序,每个任务能在1个单位完成.但是有规定一个非负整数n代表两个相同任务之间需要至少n个时间单位.球最少数量的时间单位完成所 ...