最近接手一个Web三维项目,前后端分离,前端是传统的前端项目,但又是模块化的开发方式,在修改的过程中,我需要做一些增删改查的功能,又想尽可能少的写css、尽可能少的直接操作DOM元素,所以引入了element-ui和vue,但是又不想依赖nodejs和webpack,不想引入相关配置文件,就实现了一个方案:

如何在传统前端项目中进行javascript模块化编程,并引入使用vue.js、element-ui,并且不依赖nodejs和webpack?

这里有一个问题,如果前端页面使用.vue扩展名,又没有相关配置,vscode不识别,没有代码着色,一片白,所以我是直接在html文件中写模块的css和template。

该方案开发的项目的源代码,直接扔到IIS就能跑,无需打包。

以 CameraRelation 这个模块为例:

一、在index.html中引用vue.js、element-ui的css、element-ui的js

在index.html中添加:

<link type="text/css" rel="stylesheet" href="build/element-ui/index.css">
<script type="text/javascript" src="build/vue/vue.js"></script>
<script type="text/javascript" src="build/element-ui/index.js"></script>

二、编写模块的html

cameraRelation.html代码:

<html>

<head>
<style type="text/css">
.cameraRelation-rightContainer {
line-height: 38px;
}
</style>
</head> <body>
<div id="cameraRelation">
<el-dialog title="摄像机设备关联模型" :visible.sync="dialogVisible" width="1300px" :before-close="handleClose"
:close-on-press-escape="false" :close-on-click-modal="false"> <el-row :gutter="20">
<el-col :span="6" class="cameraRelation-rightContainer">
<span>模型ID:</span>
<span>{{modelIds}}</span>
</el-col>
<el-col :span="12" class="cameraRelation-rightContainer">
<span>模型名称:</span>
<span>{{modelNames}}</span>
</el-col>
<el-col :span="4">
<el-input placeholder="请输入内容" v-model="input" clearable>
</el-input>
</el-col>
<el-col :span="2">
<el-button type="primary" @click="search()">查询</el-button>
</el-col>
</el-row> <el-row>
<el-table ref="singleTable" :data="tableData" highlight-current-row
@current-change="handleCurrentChange" style="width: 100%" height="400">
<el-table-column type="index" width="50">
</el-table-column>
<el-table-column property="id" label="摄像机ID" width="400">
</el-table-column>
<el-table-column property="name" label="摄像机名称">
</el-table-column>
<el-table-column property="modelId" label="关联模型ID集合" width="200">
</el-table-column>
<el-table-column property="modelName" label="关联模型名称集合" width="200">
</el-table-column>
</el-table>
<!--
<div style="margin-top: 20px">
<el-button @click="setCurrent(tableData[1])">选中第二行</el-button>
<el-button @click="setCurrent()">取消选择</el-button>
</div>
-->
</el-row> <span slot="footer" class="dialog-footer">
<el-button type="primary" @click="deleteRelation">删除关联</el-button>
<el-button type="primary" @click="ok">关 联</el-button>
</span> </el-dialog>
</div>
</body> </html>

三、编写模块的js

CameraRelation.js代码:

/**
* 平台摄像机关联模型
*/ import { API } from '../js.my/API.js';
import { Msg } from '../js.my/Msg.js';
import { LoadHtml } from '../js.my/LoadHtml.js'; let api = new API();
let msg = new Msg();
let loadHtml = new LoadHtml(); loadHtml.load('./view/cameraRelation.html', 'cameraRelation-container'); let vue = new Vue({
el: "#cameraRelation",
created() { },
data() {
return {
dialogVisible: false,
input: '',
modelIds: '',
modelNames: '',
tableData: [{
id: '',
name: '',
modelId: '',
modelName: ''
}],
currentRow: null
};
},
methods: {
handleClose(done) {
done();
},
ok() {
if (this.currentRow) {
msg.confirm("确定关联?", "提示", () => {
let data = {
id: this.currentRow.id,
name: this.currentRow.name,
model_id: this.modelIds,
model_name: this.modelNames
} api.updatePtCameraInfo(data, () => {
this.search();
msg.show("模型关联摄像机设备成功");
});
});
} else {
msg.show("请点击选择一条数据");
}
},
deleteRelation() {
if (this.currentRow) {
msg.confirm("确定删除该摄像机设备的模型关联?", "提示", () => {
let data = {
id: this.currentRow.id,
name: this.currentRow.name,
model_id: '',
model_name: ''
} api.updatePtCameraInfo(data, () => {
this.search();
msg.show("摄像机设备删除模型关联成功");
});
});
} else {
msg.show("请点击选择一条数据");
}
},
show(modelIds, modelNames) {
this.modelIds = modelIds;
this.modelNames = modelNames;
this.dialogVisible = true;
this.search();
},
search() {
api.getPtCameraList(this.input.trim(), data => {
this.tableData = data;
});
},
setCurrent(row) {
this.$refs.singleTable.setCurrentRow(row);
},
handleCurrentChange(val) {
this.currentRow = val;
}
}
}); let CameraRelation = function () {
this.show = vue.show;
} CameraRelation.prototype.constructor = CameraRelation; export { CameraRelation }

CameraRelation.js代码中使用了Vue,使用了LoadHtml.js模块以同步的方式加载cameraRelation.html

四、同步方式加载html的工具类

该模块使用了jquery

代码中为什么不把请求到的html内容直接添加到body中,而是再包裹一层div?因为直接添加到body中导致其他功能报错,即使把内容中的html、head、body标签去除也不行。

/**
* 同步加载html
*/ let LoadHtml = function () { /**
* 同步加载html
* @param {string} url html的url地址
* @param {string} containerId div容器id
*/
this.load = function (url, containerId) {
$.ajax({
url: url,
type: 'GET',
dataType: 'html',
async: false, //同步方式请求
success: function (data) {
if ($('#' + containerId).length == 0) {
$('body').append('<div id="' + containerId + '"></div>');
$('#' + containerId).html(data);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
if (XMLHttpRequest.responseText) {
console.log("网络请求出错:", XMLHttpRequest.responseText);
} else {
console.log("网络请求出错:", XMLHttpRequest);
}
}
});
} } LoadHtml.prototype.constructor = LoadHtml; export { LoadHtml }

五、在CameraRelation.js模块中加载依赖的cameraRelation.html

首先导入模块:

import { LoadHtml } from '../js.my/LoadHtml.js';

然后加载cameraRelation.html:

let loadHtml = new LoadHtml();

loadHtml.load('./view/cameraRelation.html', 'cameraRelation-container');

六、index.html中引用show.js

show.js是和index.html对应的业务功能的主模块

<script type="module" src="./js/show.js"></script>

七、在show.js文件中引入并使用CameraRelation模块:

Ray2.js模块用于在三维场景中拾取三维模型,然后使用对话框模块CameraRelation.js显示编辑界面

import { CameraRelation } from '../js.my/CameraRelation.js';
import { Ray2 } from '../js.my/Ray2.js'; let cameraRelation;
let ray2; //平台摄像机关联模型
let rayCallback = function (result) {
if (result.length > 0) {
let modelIds = "";
let modelNames = ""; let pos = result[0].name.lastIndexOf('_');
let namePre = result[0].name.substr(0, pos); objects.all.map(obj => {
if (obj.name.indexOf(namePre) >= 0) {
modelIds += obj.id + ",";
modelNames += obj.name + ",";
}
}); if (!cameraRelation) {
cameraRelation = new CameraRelation();
} cameraRelation.show(modelIds, modelNames);
}
}
$("#ray-start").on("click", function (event) {
if (!ray2) {
ray2 = new Ray2();
ray2.config(objects, camera, scene, "GV", rayCallback);
ray2.start();
} else {
ray2.start();
}
msg.show("请点击选择摄像机模型");
});
$("#ray-stop").on("click", function (event) {
if (ray2) {
ray2.stop();
msg.show("摄像机关联模型操作结束");
}
});

如何支持.vue扩展名的文件?
在LoadHtml工具类中加入如下代码:

/**
* 同步加载vue文件
* @param {string} url vue文件的url地址
* @param {string} containerId div容器id
*/
static loadVue = function (url, containerId) {
$.ajax({
url: url,
type: 'GET',
dataType: 'html',
async: false,
success: function (data) {
let regTmpl = /<template[^>]*>([\s\S]*)<\/template[^>]*>/;
let regStyle = /<style[^>]*>([\s\S]*)<\/style[^>]*>/;
let template = regTmpl.exec(data)[1];
let style = regStyle.exec(data)[1]; if ($('#' + containerId).length == 0) {
$('body').append('<div id="' + containerId + '"></div>');
$('#' + containerId).html(template + '<style type="text/css">' + style + '</style>');
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
if (XMLHttpRequest.responseText) {
console.error("网络请求出错:", XMLHttpRequest.responseText);
} else {
console.error("网络请求出错:", XMLHttpRequest);
}
}
});
}

使用示例:

LoadHtml.loadVue('../views/switchMapControl.vue', 'switchMapControlContainer');

效果图:

如何在传统前端项目中进行javascript模块化编程,并引入使用vue.js、element-ui,并且不依赖nodejs和webpack?的更多相关文章

  1. 在Vue3+TypeScript 前端项目中使用事件总线Mitt

    事件总线Mitt使用非常简单,本篇随笔介绍在Vue3+TypeScript 前端项目中使用的一些场景和思路.我们在Vue 的项目中,经常会通过emits 触发事件来通知组件或者页面进行相应的处理,不过 ...

  2. 前端项目中gulp的使用

    在公司项目开发中,有一个前端项目,我们使用gulp来生成目标文件(css,js,html文件) 进入到这个项目目录中  C:\My Project\FrontEnd\TestBuilder 然后依次运 ...

  3. 前端项目中使用jsencrypt进行字段加密

    前端项目中使用jsencrypt进行字段加密. 使用步骤:①获取公钥②实例化对象③设置公钥④将所需数据进行加密然后返回. 进行一个简单的封装如下 /** * npm install jsencrypt ...

  4. 在Vue&Element前端项目中,使用FastReport + pdf.js生成并展示自定义报表

    在我的<FastReport报表随笔>介绍过各种FastReport的报表设计和使用,FastReport报表可以弹性的独立设计格式,并可以在Asp.net网站上.Winform端上使用, ...

  5. 在Vue&Element前端项目中,对于字典列表的显示处理

    在很多项目开发中,我们为了使用方便,一般都会封装一些自定义组件来简化界面的显示处理,例如参照字典的下拉列表显示,是我们项目中经常用到的功能之一,本篇随笔介绍在Vue&Element前端项目中如 ...

  6. 在Vue前端项目中,附件展示的自定义组件开发

    在Vue前端界面中,自定义组件很重要,也很方便,我们一般是把一些通用的界面模块进行拆分,创建自己的自定义组件,这样操作可以大大降低页面的代码量,以及提高功能模块的开发效率,本篇随笔继续介绍在Vue&a ...

  7. 在基于vue-next-admin的Vue3+TypeScript前端项目中,为了使用方便全局挂载的对象接口

    在基于vue-next-admin 的 Vue3+TypeScript 前端项目中,可以整合自己的 .NET 后端,前端操作一些功能的时候,为了使用方便全局挂载的对象接口,以便能够快速处理一些特殊的操 ...

  8. Javascript模块化编程(一):模块的写法 (转载 学习中。。。。)

    转载地址:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html 阮一峰 大神:http://www.ruanyifeng.com/ ...

  9. javascript模块化编程思想、实现与规范

    随着BS架构的发展,网站逐渐变成了互联网应用程序,嵌入网络的JavaScript代码越来越庞大,越来越复杂(业务逻辑处理或用户交互很多写在前端).网页越来越像桌面程序,需要一个团队分工协作.进度管理. ...

  10. 简述JavaScript模块化编程(一)

    在早期编写JavaScript时,我们只需在<script>标签内写入JavaScript的代码就可以满足我们对页面交互的需要了.但随着时间的推移,时代的发展,原本的那种简单粗暴的编写方式 ...

随机推荐

  1. centos 7.9安装Prometheus

    一.Prometheus功能 Prometheus 在系统监控和警报方面非常强大,它适用于多种应用场景.以下是一些常见的 Prometheus 应用场景,以及具体的例子: 性能监控:Prometheu ...

  2. 2023-11-25:用go语言,给定一个数组arr,长度为n,表示n个格子的分数,并且这些格子首尾相连, 孩子不能选相邻的格子,不能回头选,不能选超过一圈, 但是孩子可以决定从任何位置开始选,也可以

    2023-11-25:用go语言,给定一个数组arr,长度为n,表示n个格子的分数,并且这些格子首尾相连, 孩子不能选相邻的格子,不能回头选,不能选超过一圈, 但是孩子可以决定从任何位置开始选,也可以 ...

  3. 面试题——为什么 Vue 中不要用 index 作为 key?(diff 算法详解)

    前言 在vue中使用v-for时需要,都会提示或要求使用  :key,有的的开发者会直接使用数组的 index 作为 key 的值,但不建议直接使用 index作为 key 的值,有时我们面试时也会遇 ...

  4. 快速认识,前端必学编程语言:JavaScript

    JavaScript是构建Web应用必学的一门编程语言,也是最受开发者欢迎的热门语言之一.所以,如果您还不知道JavaScript的用处.特点的话,赶紧补充一下这块基础知识. JavaScript 是 ...

  5. LeetCode1806:还原排列的最少操作步数(置换群 or 模拟)

    题意:题目的意思是,给定一个初始状态perm,然后对perm的每个元素按照上述的规则进行变换操作.问:perm经过多少次这种操作能够变回初始的perm. 解题思路:第一种方法就是模拟,一直变换,直到变 ...

  6. ElasticSearch安装中文分词器(插件)、分词测试

    https://github.com/medcl/elasticsearch-analysis-ik 分词测试: https://www.elastic.co/guide/en/elasticsear ...

  7. 使用dtd定义元素

  8. 有意思,我的GitHub账号值$23806.2,快来试试你的?

    睡不着,看到一个有意思的网站:Estimate Github Worth Generator. 它可以用来估算 GitHub 账号的价值.马上试了一下. 我的账号估值:$23806.2 操作很简单,点 ...

  9. K8s和声明式编程

    转载:原文链接 认识k8s之后,他的操作模式对我来说是一种很不错的体验.他提供了更接近现实世界的面向对象接口. 什么是k8s? Kubernetes(K8s)是一种开源容器编排平台,用于自动化部署.扩 ...

  10. k8s环境设置-pod下载及重启策略

    k8s环境设置 在我们开始使用k8s之前,我们可以先做一些环境配置,使k8s更加的方便使用 第一个要做的就是kubectl命令的补全 在使用kubectl的时候你会发现参数你是Tab不出来的,这时候我 ...