首页 web前端 js教程 JS组件Bootstrap Table表格多行拖拽效果实现代码

JS组件Bootstrap Table表格多行拖拽效果实现代码

Jan 04, 2017 am 10:54 AM

前言:前天刚写了篇JS组件Bootstrap Table表格行拖拽效果,今天接到新的需要,需要在之前表格行拖拽的基础上能够同时拖拽选中的多行。用了半天时间研究了下,效果是出来了,但是感觉不尽如人意。先把它分享出来,以后想到更好的办法再优化吧。

一、效果展示

1、拖动前

2016110316252934.png

2、拖动中

2016110316252934.png

3、拖动后

2016110316252934.png

4、撤销回到拖动前状态

2016110316252934.png

二、需求分析
通过上篇我们知道,如果要实现拖拽,必须要有一个可以拖拽的标签,或者叫容器,比如上篇里面的tr就是一个拖拽的容器,那么如果要实现选择行的拖拽,那么博主的第一反应是将选中的行放到一个容器里面,比如放到一个div中,然后注册这个div的可拖拽,可是实际情况是,tr是在table里面的标签,如果将tr用div包起来,势必将table里面的样式打乱,这个界面就真的是乱掉了。很显然,这条路走不通。然后通过谷歌浏览器审核元素知道,用Bootstrap table生成的表格tr的父级元素实际上是tbody,于是在想是否可以注册tbody的拖拽,实践证明,此法可行。于是就此开干。

三、代码示例
cshtm的代码就不再重复,和上篇相同。我们重点来看看js代码。

var i_statuindex = 0;
var arrdata = [];
 
var m_oTable = null;
 
$(function () {
 //1.初始化表格
 m_oTable = new TableInit();
 m_oTable.Init();
 
 //2.初始化按钮事件
 var oButtonInit = new ButtonInit();
 oButtonInit.Init();
 
 //3.日期控件的初始化
 $(".datetimepicker").datetimepicker({
 format: 'yyyy-mm-dd hh:ii',
 autoclose: true,
 todayBtn: true,
 });
 
});
 
//表格相关事件和方法
var TableInit = function () {
 var oTableInit = new Object();
 
 oTableInit.Init = function () {
 $('#tb_order_left').bootstrapTable({
 url: '/api/OrderApi/get',
 method: 'get',
 striped: true,
 cache: false,
 striped: true,
 pagination: true,
 height: 600,
 uniqueId:"TO_ORDER_ID",
 queryParams: oTableInit.queryParams,
 queryParamsType: "limit",
 sidePagination: "server",
 pageSize: 10,
 pageList: [10, 25, 50, 100],
 search: true,
 strictSearch: true,
 showColumns: true,
 showRefresh: true,
 minimumCountColumns: 2,
 clickToSelect: true,
 columns: [{
 checkbox: true
 },
 {
 field: 'ORDER_NO',
 title: '订单号'
 },
 {
 field: 'BODY_NO',
 title: '车身号'
 }, {
 field: 'VIN',
 title: 'VIN码'
 }, {
 field: 'TM_MODEL_MATERIAL_ID',
 title: '整车编码'
 },
 {
 field: 'ORDER_TYPE',
 title: '订单类型'
 },
 {
 field: 'ORDER_STATUS',
 title: '订单状态'
 },
 {
 field: 'CREATE_DATE',
 title: '订单导入时间'
 },
 {
 field: 'PLAN_DATE',
 title: '订单计划上线日期'
 },
 {
 field: 'VMS_NO',
 title: 'VMS号'
 },
 {
 field: 'ENGIN_CODE',
 title: '发动机号'
 },
 {
 field: 'TRANS_CODE',
 title: '变速箱号'
 },
 {
 field: 'OFFLINE_DATE_ACT',
 title: '实际下线日期'
 },
 {
 field: 'HOLD_RES',
 title: 'hold理由'
 },
 {
 field: 'SPC_FLAG',
 title: '特殊标记'
 },
 ],
 onLoadSuccess: function (data) {
 oTableInit.InitDrag();
 if (data.total > 0) {
 var iheight = $('#div_tableleft').find(".fixed-table-container").height();
 $('#div_tableleft').find(".fixed-table-container").height(iheight + 36);
 }
 },
 onCheckAll: function (rows) {
 $("#tb_order_left tbody tr").addClass("selected");
 },
 onUncheckAll: function (rows) {
 $("#tb_order_left tbody tr").removeClass("selected");
 }
 });
 
 $('#tb_order_right').bootstrapTable({
 url: '/api/OrderApi/get',
 method: 'get',
 toolbar: '#toolbar_right',
 striped: true,
 cache: false,
 striped: true,
 pagination: true,
 height: 600,
 queryParams: oTableInit.queryParamsRight,
 queryParamsType: "limit",
 //ajaxOptions: { departmentname: "", statu: "" },
 sidePagination: "server",
 pageSize: 10,
 pageList: [10, 25, 50, 100],
 search: true,
 strictSearch: true,
 showRefresh: true,
 minimumCountColumns: 2,
 columns: [
 {
 field: 'ORDER_NO',
 title: '订单号'
 },
 {
 field: 'BODY_NO',
 title: '车身号'
 }, {
 field: 'VIN',
 title: 'VIN码'
 }, {
 field: 'TM_MODEL_MATERIAL_ID',
 title: '整车编码'
 },
 {
 field: 'ORDER_TYPE',
 title: '订单类型'
 },
 {
 field: 'ORDER_STATUS',
 title: '订单状态'
 },
 {
 field: 'CREATE_DATE',
 title: '订单导入时间'
 },
 {
 field: 'PLAN_DATE',
 title: '订单计划上线日期'
 },
 {
 field: 'VMS_NO',
 title: 'VMS号'
 },
 {
 field: 'ENGIN_CODE',
 title: '发动机号'
 },
 {
 field: 'TRANS_CODE',
 title: '变速箱号'
 },
 {
 field: 'OFFLINE_DATE_ACT',
 title: '实际下线日期'
 },
 {
 field: 'HOLD_RES',
 title: 'hold理由'
 },
 {
 field: 'SPC_FLAG',
 title: '特殊标记'
 },
 ],
 onLoadSuccess: function (data) {
 oTableInit.InitDrop();
 }
 });
 };
 
 oTableInit.InitDrag = function () {
 $('#tb_order_left tbody').draggable({
 helper: "clone",
 start: function (event, ui) {
 var old_left_data = JSON.stringify($('#tb_order_left').bootstrapTable("getData"));
 var old_right_data = JSON.stringify($('#tb_order_right').bootstrapTable("getData"));
 var odata = { index: ++i_statuindex, left_data: old_left_data, right_data: old_right_data };
 arrdata.push(odata);
 },
 stop: function (event, ui) {
 }
 });
 };
 
 oTableInit.InitDrop = function () {
 $("#div_tableright div[class=fixed-table-container]").droppable({
 drop: function (event, ui) {
 var arrtr = $(ui.helper[0]).find("tr[class=selected]");
 if (arrtr.length <= 0) {
 alert("请先选中要插单的行");
 return;
 }
 var oTop = ui.helper[0].offsetTop;
 var iRowHeadHeight = 40;
 var iRowHeight = 37;
 var rowIndex = 0;
 if (oTop <= iRowHeadHeight + iRowHeight / 2) {
 rowIndex = 0;
 }
 else {
 rowIndex = Math.ceil((oTop - iRowHeadHeight) / iRowHeight);
 }
 for (var i = 0; i < arrtr.length; i++) {
 var arrtd = $(arrtr[i]).find("td");
 var uniqueid = $(arrtr[i]).attr("data-uniqueid");
 var rowdata = {
 ORDER_NO: $(arrtd[1]).text(),
 BODY_NO: $(arrtd[2]).text(),
 VIN: $(arrtd[3]).text(),
 TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(),
 ORDER_TYPE: $(arrtd[5]).text(),
 ORDER_STATUS: $(arrtd[6]).text(),
 CREATE_DATE: $(arrtd[7]).text() == "-" ? null : $(arrtd[7]).text(),
 PLAN_DATE: $(arrtd[8]).text() == "-" ? null : $(arrtd[8]).text(),
 VMS_NO: $(arrtd[9]).text(),
 ENGIN_CODE: $(arrtd[10]).text(),
 TRANS_CODE: $(arrtd[11]).text(),
 OFFLINE_DATE_ACT: $(arrtd[12]).text() == "-" ? null : $(arrtd[12]).text(),
 HOLD_RES: $(arrtd[13]).text(),
 SPC_FLAG: $(arrtd[14]).text(),
 TO_ORDER_ID: uniqueid
 
 };
 $("#tb_order_right").bootstrapTable("insertRow", { index: rowIndex++, row: rowdata });
 $(&#39;#tb_order_left&#39;).bootstrapTable("removeByUniqueId", uniqueid);
 }
  
  
 oTableInit.InitDrag();
 }
 });
 };
 
 oTableInit.queryParams = function (params) { //配置参数
 var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
 limit: params.limit, //页面大小
 offset: params.offset, //页码
 strBodyno: $("#txt_search_bodynumber").val(),
 strVin: $("#txt_search_vinnumber").val(),
 strOrderno: $("#txt_search_ordernumber").val(),
 strEngincode: $("#txt_search_engin_code").val(),
 strOrderstatus: 0,
 strTranscode: $("#txt_search_trans_code").val(),
 strVms: $("#txt_search_vms").val(),
 strCarcode: $("#txt_search_carcode").val(),
 strImportStartdate: $("#txt_search_import_startdate").val(),
 strImportEnddate: $("#txt_search_import_enddate").val(),
 strSendStartdate: $("#txt_search_send_startdate").val(),
 strSendEnddate: $("#txt_search_send_enddate").val(),
 
 };
 return temp;
 };
 
 oTableInit.queryParamsRight = function (params) { //配置参数
 var temp = { //这里的键的名字和控制器的变量名必须一直,这边改动,控制器也需要改成一样的
 limit: params.limit, //页面大小
 offset: params.offset, //页码
 strBodyno: "",
 strVin: "",
 strOrderno: "",
 strEngincode: "",
 strOrderstatus: 5,
 strTranscode: "",
 strVms: "",
 strCarcode: "",
 strImportStartdate: "",
 strImportEnddate: "",
 strSendStartdate: "",
 strSendEnddate: "",
 
 };
 return temp;
 };
 
 return oTableInit;
};
 
//页面按钮初始化事件
var ButtonInit = function () {
 var oInit = new Object();
 var postdata = {};
 
 oInit.Init = function () {
 
 //查询点击事件
 $("#btn_query").click(function () {
 $("#tb_order_left").bootstrapTable(&#39;refresh&#39;);
 });
 
 //重置点击事件
 $("#btn_reset").click(function () {
 $(".container-fluid").find(".form-control").val("");
 $("#tb_order_left").bootstrapTable(&#39;refresh&#39;);
 });
 
 //插单操作点击事件
 $("#btn_insertorder").click(function () {
  
 });
 
 //撤销操作点击事件
 $("#btn_cancel").click(function () {
 if (i_statuindex <= 0) {
 return;
 }
 for (var i = 0; i < arrdata.length; i++) {
 if (arrdata[i].index != i_statuindex) {
 continue;
 }
 var arr_left_data = eval(arrdata[i].left_data);
 var arr_right_data = eval(arrdata[i].right_data);
 
 $(&#39;#tb_order_left&#39;).bootstrapTable(&#39;removeAll&#39;);
 $(&#39;#tb_order_right&#39;).bootstrapTable(&#39;removeAll&#39;);
 $(&#39;#tb_order_left&#39;).bootstrapTable(&#39;append&#39;, arr_left_data);
 for (var x = 0; x < arr_right_data.length; x++) {
 $("#tb_order_right").bootstrapTable("insertRow", { index: x, row: arr_right_data[x] });
 }
  
 //$(&#39;#tb_order_right&#39;).bootstrapTable(&#39;append&#39;, arr_right_data);//append之后不能drop
 break;
 }
 i_statuindex--;
 
 //重新注册可拖拽
 m_oTable.InitDrag();
 //m_oTable.InitDrop();
 });
 };
 
 return oInit;
};
登录后复制

还是重点看看部分代码

1、注册左边可拖拽

$(&#39;#tb_order_left tbody&#39;).draggable({
 helper: "clone",
 start: function (event, ui) {
 var old_left_data = JSON.stringify($(&#39;#tb_order_left&#39;).bootstrapTable("getData"));
 var old_right_data = JSON.stringify($(&#39;#tb_order_right&#39;).bootstrapTable("getData"));
 var odata = { index: ++i_statuindex, left_data: old_left_data, right_data: old_right_data };
 arrdata.push(odata);
 },
 stop: function (event, ui) {
 }
 });
登录后复制

这里代码很简单,主要做了两件事:

(1)注册tbody的可拖拽,同样适用的JQuery UI的draggable事件。

(2)在开始拖拽前,保存两边表格的数据,用于还原的操作。

2、注册右边drop

   $("#div_tableright div[class=fixed-table-container]").droppable({
drop: function (event, ui) {
var arrtr = $(ui.helper[0]).find("tr[class=selected]");
if (arrtr.length <= 0) {
alert("请先选中要插单的行");
return;
}
var oTop = ui.helper[0].offsetTop;
var iRowHeadHeight = 40;
var iRowHeight = 37;
var rowIndex = 0;
if (oTop <= iRowHeadHeight + iRowHeight / 2) {
rowIndex = 0;
}
else {
rowIndex = Math.ceil((oTop - iRowHeadHeight) / iRowHeight);
}
for (var i = 0; i < arrtr.length; i++) {
var arrtd = $(arrtr[i]).find("td");
var uniqueid = $(arrtr[i]).attr("data-uniqueid");
var rowdata = {
ORDER_NO: $(arrtd[1]).text(),
BODY_NO: $(arrtd[2]).text(),
VIN: $(arrtd[3]).text(),
TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(),
ORDER_TYPE: $(arrtd[5]).text(),
ORDER_STATUS: $(arrtd[6]).text(),
CREATE_DATE: $(arrtd[7]).text() == "-" ? null : $(arrtd[7]).text(),
PLAN_DATE: $(arrtd[8]).text() == "-" ? null : $(arrtd[8]).text(),
VMS_NO: $(arrtd[9]).text(),
ENGIN_CODE: $(arrtd[10]).text(),
TRANS_CODE: $(arrtd[11]).text(),
OFFLINE_DATE_ACT: $(arrtd[12]).text() == "-" ? null : $(arrtd[12]).text(),
HOLD_RES: $(arrtd[13]).text(),
SPC_FLAG: $(arrtd[14]).text(),
TO_ORDER_ID: uniqueid
 
};
$("#tb_order_right").bootstrapTable("insertRow", { index: rowIndex++, row: rowdata });
$(&#39;#tb_order_left&#39;).bootstrapTable("removeByUniqueId", uniqueid);
}
 
 
oTableInit.InitDrag();
}
});
登录后复制

这里代码和之前有点变化

(1)注册#div_tableright div[class=fixed-table-container]标签的droppable,这个标签是Bootstrap Table表格初始化后自动生成的,为什么不直接注册表格#tb_order_right的droppable,是因为这个标签作用域太小,会导致拖过来的tbody捕捉不到drop事件。而注册表格外部的#div_tableright div[class=fixed-table-container]这个div标签可以解决问题。

(2)通过var arrtr = $(ui.helper[0]).find("tr[class=selected]");找到拖过来tbody里面选中的行,然后将数据取出依次插入右边表格,左边表格则依次删除行数据。

(3)这里有点麻烦的是找drop的位置,我们知道,要想将左边选中的行放到右边指定的位置,那么就得得到当前鼠标drop的位置,这里通过ui.helper[0].offsetTop属性来获得鼠标的Y轴位置,通过计算得到要插入的位置。

3、撤销操作  

$("#btn_cancel").click(function () {
if (i_statuindex <= 0) {
return;
}
for (var i = 0; i < arrdata.length; i++) {
if (arrdata[i].index != i_statuindex) {
continue;
}
var arr_left_data = eval(arrdata[i].left_data);
var arr_right_data = eval(arrdata[i].right_data);
 
$(&#39;#tb_order_left&#39;).bootstrapTable(&#39;removeAll&#39;);
$(&#39;#tb_order_right&#39;).bootstrapTable(&#39;removeAll&#39;);
$(&#39;#tb_order_left&#39;).bootstrapTable(&#39;append&#39;, arr_left_data);
for (var x = 0; x < arr_right_data.length; x++) {
$("#tb_order_right").bootstrapTable("insertRow", { index: x, row: arr_right_data[x] });
}
 
//$(&#39;#tb_order_right&#39;).bootstrapTable(&#39;append&#39;, arr_right_data);//append之后不能drop
break;
}
i_statuindex--;
 
//重写注册可拖拽
m_oTable.InitDrag();
//m_oTable.InitDrop();
});
登录后复制

撤销操作和之前也基本相同。

四、总结
效果是完成了,美中不足的是每次拖过去的都是整个tbody,而不是选中的行,奈何多个选中的行无法用某一个容器包起来。暂时没找到合适的解决方案。先这样吧,等以后想到好的方案了再优化吧。

五、优化方案

1、注册drap的方法

oTableInit.InitDrag = function () {
 $(&#39;#tb_order_left tbody&#39;).draggable({
 helper: "clone",
 start: function (event, ui) {
 var old_left_data = JSON.stringify($(&#39;#tb_order_left&#39;).bootstrapTable("getData"));
 var old_right_data = JSON.stringify($(&#39;#tb_order_right&#39;).bootstrapTable("getData"));
 var odata = { index: ++i_statuindex, left_data: old_left_data, right_data: old_right_data };
 arrdata.push(odata);
 $(ui.helper[0]).find("tr[class!=selected]").remove();
 },
 stop: function (event, ui) {
 }
 });
 };
登录后复制

增加了这一句$(ui.helper[0]).find("tr[class!=selected]").remove();这样在拖动的时候就看不到未选中的行了。
2、精准定位到右边表格指定位置:

oTableInit.InitDrop = function () {
 $("#div_tableright div[class=fixed-table-container]").droppable({
 drop: function (event, ui) {
 var arrtr = $(ui.helper[0]).find("tr[class=selected]");
 if (arrtr.length <= 0) {
 toastr.warning(&#39;请先选中要插单的行&#39;);
 return;
 }
 var oTop = ui.helper[0].offsetTop;
 //因为表格每行的高度可能不一致,所以这里取插入行位置的办法是:取右边表格的行高依次累加,计算行索引。
 var rowIndex = 0;
 var bIsBottom = true;
 var iRowHeadHeight = 40;
 var addHeight = iRowHeadHeight;
 var trs = $("#tb_order_right tbody tr");
 for (var i = 0; i < trs.length; i++) {
 addHeight += $(trs[i]).height();
 if (addHeight > oTop) {
 rowIndex = i;
 bIsBottom = false;//这里参数用来定义拖动到右边表格最下面的情况,这时没有进入到此条件判断里面。
 break;
 }
 }
 if (bIsBottom) {
 rowIndex = trs.length;
 }
 
 for (var i = 0; i < arrtr.length; i++) {
 var arrtd = $(arrtr[i]).find("td");
 var uniqueid = $(arrtr[i]).attr("data-uniqueid");
 var rowdata = {
 ORDER_NO: $(arrtd[1]).text(),
 BODY_NO: $(arrtd[2]).text(),
 VIN: $(arrtd[3]).text(),
 TM_MODEL_MATERIAL_ID: $(arrtd[4]).text(),
 ORDER_TYPE: $(arrtd[5]).text(),
 ORDER_STATUS_NAME: $(arrtd[6]).text(),
 CREATE_DATE: $(arrtd[7]).text() == "-" ? null : $(arrtd[7]).text(),
 PLAN_DATE: $(arrtd[8]).text() == "-" ? null : $(arrtd[8]).text(),
 VMS_NO: $(arrtd[9]).text(),
 ENGIN_CODE: $(arrtd[10]).text(),
 TRANS_CODE: $(arrtd[11]).text(),
 OFFLINE_DATE_ACT: $(arrtd[12]).text() == "-" ? null : $(arrtd[12]).text(),
 HOLD_RES: $(arrtd[13]).text(),
 SPC_FLAG: $(arrtd[14]).text(),
 TO_ORDER_ID: uniqueid,
 ORDER_STATUS:0
 
 };
 $("#tb_order_right").bootstrapTable("insertRow", { index: rowIndex++, row: rowdata });
 $(&#39;#tb_order_left&#39;).bootstrapTable("removeByUniqueId", uniqueid);
 }
 
 oTableInit.InitDrag();
 
 }
 });
 };
登录后复制

因为每一行的行高不确定,是由行里面的数据动态撑出来的,所以这里也动态计算drop的位置。

至此,这个小的功能基本告一段落,基本的效果和待优化点也完成了。

更多JS组件Bootstrap Table表格多行拖拽效果实现代码相关文章请关注PHP中文网!


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

console.log输出结果差异:两次调用为何不同? console.log输出结果差异:两次调用为何不同? Apr 04, 2025 pm 05:12 PM

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

初学者的打字稿,第2部分:基本数据类型 初学者的打字稿,第2部分:基本数据类型 Mar 19, 2025 am 09:10 AM

掌握了入门级TypeScript教程后,您应该能够在支持TypeScript的IDE中编写自己的代码,并将其编译成JavaScript。本教程将深入探讨TypeScript中各种数据类型。 JavaScript拥有七种数据类型:Null、Undefined、Boolean、Number、String、Symbol(ES6引入)和Object。TypeScript在此基础上定义了更多类型,本教程将详细介绍所有这些类型。 Null数据类型 与JavaScript一样,TypeScript中的null

PowerPoint可以运行JavaScript吗? PowerPoint可以运行JavaScript吗? Apr 01, 2025 pm 05:17 PM

在PowerPoint中可以运行JavaScript,通过VBA调用外部JavaScript文件或嵌入HTML文件来实现。1.使用VBA调用JavaScript文件,需启用宏并具备VBA编程知识。2.嵌入包含JavaScript的HTML文件,简单易行但受安全限制。优点包括扩展功能和灵活性,劣势涉及安全性、兼容性和复杂性,实际应用需注意安全性、兼容性、性能和用户体验。

See all articles