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

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

  1. import {
  2. invokeServiceWait,
  3. checkRequestStatus,
  4. handleCallbackFn,
  5. } from "@/InitMethods/formHttp";
  6. export default {
  7. data() {
  8. return {
  9. _form: null,
  10. isStartLoad: false,
  11. };
  12. },
  13. methods: {
  14. /**
  15. * 替换元素的style font-size
  16. */
  17. replaceStyleFontSize(templateStr){
  18. let fontSize = localStorage.getItem('fontSizeMultiplier');
  19. // 存在获取fontSizeMultiplier为null时 默认字体放大倍数取1
  20. fontSize==null?fontSize=1:fontSize;
  21. if(fontSize){
  22. let fontSizeExp= /(\s?font-size:\s?)([0-9.]+)([a-zA-Z]*)/g
  23.  
  24. //let fontSizeExp = /(\s?font-size:\s?)([0-9.]+)([a-zA-Z]*[\s|;|}|\)])/g;
  25. templateStr= templateStr.replace(fontSizeExp,(match, key, n, unit) => {
  26. console.log(match)
  27. return key + Number(n) * fontSize + unit;
  28. })
  29. return templateStr
  30. }
  31.  
  32. },
  33. /**
  34. * 服务器表单字符串转化Vue表单挂在到对应DOM节点
  35. *
  36. * @param {String} formStr VueFrom文件的字符串
  37. * @param {String} queryStr Vue实例需要挂在DOM节点的id或者class
  38. *
  39. */
  40. strToVueForm(formStr, queryStr) {
  41. if (typeof formStr == "string" && formStr.length) {
  42. // 检查id是否存在
  43. if (!document.querySelector(`${queryStr}`)) {
  44. console.error('"id" or "class" does not exist!');
  45. return {};
  46. }
  47. let fromStyleDom = null;
  48. let styleBegin = 0; // style截取开始位置
  49. let styleEnd = 0; // style截取结束位置
  50. let templateBegin = 0; // template截取开始位置
  51. let templateEnd = 0; // template截取结束位置
  52. let scriptBegin = 0; // script截取开始位置
  53. let scriptEnd = 0; // script截取结束位置
  54.  
  55. // 解析Vue字符串文件中的样式并添加到app全局中
  56. if (formStr.indexOf("<style") > -1) {
  57. styleBegin = formStr.indexOf("<style") + "<style".length;
  58. styleEnd = formStr.indexOf("</style>");
  59. let styleStr = formStr.substring(styleBegin, styleEnd);
  60. // 再次去除stlye中的属性设置(例如:lang="sass" scoped)
  61. let styleStartIndex = styleStr.indexOf(">") + 1;
  62. styleStr = styleStr.substring(styleStartIndex);
  63. // 添加到全局样式中
  64. if (styleStr) {
  65. fromStyleDom = document.createElement("style");
  66. fromStyleDom.innerHTML = styleStr;
  67. // style样式插入header中
  68. document.head.appendChild(fromStyleDom);
  69. }
  70. }
  71.  
  72. // 解析Vue字符串模板中的template以及script并挂到对应的dom节点
  73. templateBegin = formStr.indexOf("<template>") + "<template>".length;
  74. templateEnd = formStr.lastIndexOf("</template>");
  75. let templateStr = formStr.substring(templateBegin, templateEnd);
  76. templateStr = templateStr
  77. .replace(/\r\n/g, " ")
  78. .replace(/\n/g, " ")
  79. .replace(/"/g, '\\"');
  80. console.log("templateStr前",templateStr)
  81. templateStr=this.replaceStyleFontSize(templateStr)
  82. console.log("templateStr后",templateStr)
  83. templateStr = 'let formtemplate ="' + templateStr + '";\n';
  84. scriptBegin = formStr.indexOf("<script>") + "<script>".length;
  85. scriptEnd = formStr.indexOf("</script>");
  86. let scriptStr = formStr.substring(scriptBegin, scriptEnd);
  87. // 防止window.vue.extend之前还定义了变量导致Cusform赋值无法得到window.vue.extend
  88. if (scriptStr.indexOf(window.vue.extend) != 0) {
  89. scriptStr = scriptStr.replace(
  90. /window.vue.extend/,
  91. "var Cusform = window.vue.extend"
  92. );
  93. } else {
  94. scriptStr = "let Cusform =" + scriptStr;
  95. }
  96. let insetIndex =
  97. scriptStr.indexOf("window.vue.extend({") +
  98. "window.vue.extend({".length;
  99. // 添加beforeDestroy
  100. let destroyMixinStr = `
  101. mixins:[{
  102. beforeDestroy: function() {
  103. fromStyleDom && fromStyleDom.remove()
  104. }
  105. }],`;
  106. scriptStr =
  107. scriptStr.slice(0, insetIndex) +
  108. destroyMixinStr +
  109. scriptStr.slice(insetIndex);
  110. // console.log("scriptStr:", scriptStr);
  111. let Cusform = eval(templateStr + scriptStr + ";" + "Cusform");
  112. this.isStartLoad = false;
  113. Cusform.prototype.invokeServiceWait = invokeServiceWait;
  114. Cusform.prototype.isStartLoad = false;
  115. Cusform.prototype.checkRequestStatus = function () {
  116. return checkRequestStatus(this.isStartLoad);
  117. };
  118.  
  119. let vueForm = new Cusform().$mount(`${queryStr}`);
  120.  
  121. this._form = vueForm;
  122. vueForm.isStartLoad = true;
  123. this.isStartLoad = true;
  124.  
  125. return vueForm;
  126. } else {
  127. return {};
  128. }
  129. },
  130. },
  131. beforeDestroy() {
  132. this._form && this._form.$destroy();
  133. },
  134. };

2,如何使用:

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

新建MyPaidLeaveInfo.js文件:

  1. import strToVueFormMixin from '@/mixins/strToVueFormMixin';
  2. export default {
  3. mixins: [strToVueFormMixin],
  4. name: 'PaidLeaveInfoPC',
  5. data() {
  6. return {
  7. fileStr:'',
  8. myForm:{},
  9. formLoadStatus: null,
  10. }
  11. },
  12. mounted() {
  13. this.init();
  14. },
  15. methods: {
  16. // 获取PaidLeaveInfoPC表单
  17. getFile() {
  18. return new Promise((resolve, reject) => {
  19. this.invokeService(
  20. 'AnnualLeave',
  21. 'GetCustomForm',
  22. ['PaidLeaveInfoPC'],
  23. msg => {
  24. const $ = msg.ReturnData.$;
  25. if ($.Succeed) {
  26. const fileStr = Lark.base64Decode($.Data);
  27. this.fileStr = fileStr;
  28. resolve(fileStr);
  29. } else {
  30. reject();
  31. }
  32. },
  33. err => {
  34. reject(err);
  35. }
  36. );
  37. });
  38. },
  39. init() {
  40. this.formLoadStatus = new Promise((resolve, reject) => {
  41. this.getFile()
  42. .then(file => this.fileToHtml(file))
  43. .then(() => {
  44. resolve();
  45. })
  46. .catch(err => {
  47. console.log(err,'err');
  48. reject();
  49. });
  50. });
  51. },
  52. // 后端返回的数据转为vhtml
  53. fileToHtml(file) {
  54. file = file.replace(/wfm-popup/g, 'paidleaveinfoPC-popup');
  55. let vueForm = this.strToVueForm(file, '#paidLeaveInfoPC');
  56. this.myForm = vueForm;
  57. return Promise.resolve();
  58. }
  59. }
  60. }

新建MyPaidLeaveInfo.vue文件

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

  1. <template>
  2. <el-row>
  3. <el-header style="height: 30px" class="wfm-first-header"
  4. ><WFMBreadcrumb></WFMBreadcrumb
  5. ></el-header>
  6. <div id="paidLeaveInfoPC"></div>
  7. </el-row>
  8. </template>
  9.  
  10. <script>
  11. import MyPaidLeaveInfoJS from './MyPaidLeaveInfo.js';
  12. export default MyPaidLeaveInfoJS;
  13. </script>
  14.  
  15. <style lang="scss" scoped>
  16. @import './MyPaidLeaveInfo.scss';
  17. </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. vscode提示提示安装似乎损坏,请重新安装

    安装 Fix VSCode Checksums 插件 Ctrl+Shift+P , 输入Fix Checksums : Apply, 点击,重启即可

  2. CF1041B Buying a TV Set 题解

    Content 给定四个数 \(a,b,c,d\),求满足以下条件的数对 \((x,y)\) 的个数: \(x\leqslant a,y\leqslant b\). \(\dfrac{x}{y}=\d ...

  3. JS自动播放音频 无效chrome设置 (Uncaught (in promise) DOMException: play() failed because the user didn't interact)

    Chrome的autoplay政策在2018年4月做了更改.新的行为:浏览器为了提高用户体验,减少数据消耗,现在都在遵循autoplay政策,Chrome的autoplay 政策非常简单 muted ...

  4. python爬取信息到数据库与mysql简单的表操作

    python 爬取豆瓣top250并导入到mysql数据库中 import pymysql import requests import re url='https://movie.douban.co ...

  5. Linux(centos)创建用户并分配权限

    创建名为 elas的用户 adduser elas 初始化elas的密码 passwd elas 显示 新的 密码: 重新输入新的 密码: passwd:所有的身份验证令牌已经成功更新. 进行授权 个 ...

  6. Intellij IDEA添加插件

    1. Lombok插件 IDEA增加对Lombok的支持 <!--lombok插件--> <dependency> <groupId>org.projectlomb ...

  7. 【LeetCode】1085. Sum of Digits in the Minimum Number 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 遍历 日期 题目地址:https://leetcode ...

  8. 【LeetCode】211. Add and Search Word - Data structure design 添加与搜索单词 - 数据结构设计

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:Leetcode, 力扣,211,搜索单词,前缀树,字典树 ...

  9. LeetCode 1482. 制作 m 束花所需的最少天数

    LeetCode 1482. 制作 m 束花所需的最少天数 题目 给你一个整数数组 bloomDay,以及两个整数 m 和 k . 现需要制作 m 束花.制作花束时,需要使用花园中 相邻的 k 朵花 ...

  10. Chapter 20 Treatment-Confounder Feedback

    目录 20.1 The elements of treatment-confounder feedback 20.2 The bias of traditional methods 20.3 Why ...