搜尋
首頁web前端js教程BootstrapTable與KnockoutJS結合實作增刪改查功能【一】_javascript技巧

bootstrap是一個前端框架,解放web開發者的好東東,展現出的ui非常高端大氣上檔次,理論上可以不用寫一行css。只要在標籤中加上適當的屬性即可。

knockoutjs是一個javascript實作的mvvm框架。非常棒。例如列表資料項增減後,不需要重新刷新整個控制項片段或自己寫js增刪節點,只要預先定義模板和符合其語法定義的屬性即可。簡單的說,我們只需要關注數據的存取。

一、knockout.js簡介

1、knockout.js和mvvm

如今,各種前端框架應接不暇,令人眼花繚亂,有時不得不感嘆作為程序猿也真是苦逼,總有學不完的技術,何時是盡頭,除非你轉化!苦海無邊,回頭是不是岸,由你決定!

knockout.js是一個基於mvvm模式的輕量級的前端框架,有多輕?根據官網上方顯示的最新版本v3.4.0,僅22kb。能夠友善地處理資料模型和介面dom的綁定,最重要的是,它的綁定是雙向的,也就是說資料模型變化了,介面dom上的資料也會跟著變化,反過來,介面dom上的數據變化了,數據模型也會跟著這個變化。這樣能夠大幅減少我們的前端程式碼量,並且使得我們介面易於維護,再也不用寫一大堆事件監控資料模型和介面dom的變化了。下面部落客會根據一個使用實例來說明這兩點。

knockout.js官網:http://knockoutjs.com

knockout.js開源位址:https://github.com/knockout/knockout

mvvm模式:這是一種創建使用者介面的設計模式,mvvm把它拆分成三塊就是model、view、viewmodel,model就是資料模型,view就是我們的視圖,viewmodel就是一個視圖模型,用來綁定資料模型和視圖上面的dom元素。如果你使用過wpf和silverlight,理解這個應該不是啥問題;沒有使用過也什麼關係,看完此文,你會有一個大致的認識。

2.最簡單的實例

一般來說,如果你從零開始使用knockout.js,你至少需要做以下四部

2.1、去官網下載knockout.js文件,然後引用到view頁裡面。

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>

注意:knockout.js不需要jquery的支持,如果你的專案需要用到jquery的相關操作,則引用jquery;否則只引用以上文件即可。

2.2、定義viewmodel

viewmodel是什麼?其實,在js裡面,它看起來就像一個json物件。我們定義一個viewmodel:

var myviewmodel = {
name: "lilei",
profession: "软件工程师",
};

2.3、view視圖裡面定義綁定data-bind的標籤

<div> 
姓名:<label data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div>

注意:對應input標籤的文本,需要使用textinput,而一般標籤的文字使用text即可。

2.4、啟動綁定

做了以上三步,還需要啟動knockout的綁定

ko.applybindings(myviewmodel);

做到這四部,基本上實作了一個最簡單的viewmodel的資料綁定。

如果你夠細心,你會發現ko.applybindings()方法有兩個參數,第一個就是我們需要綁定的viewmodel,第二個又是什麼呢?由ko.applybindings(myviewmodel); 可知,第二個參數是一個可選參數,它表示viewmodel綁定的標籤的作用域,比如,我們將以上程式碼改一下:

<div> 
姓名:<label id="lb_name" data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div> 
ko.applybindings(myviewmodel,document.getelementbyid("lb_name"));

由此可知:第二個參數限定了myviewmodel的作用範圍,也就是說,只有在id="lb_name"的標籤上面綁定才會生效,如果第二個參數是div等容器標籤,它表示該綁定的範圍為該div下面的所有子標籤。

3、監控屬性

截止到上面的四步,我們看不到任何效果,看到的無非就是將一個json物件的資料綁定到了html標籤上面,這樣做有什麼意義呢?不是把簡單的問題複雜化嗎?別急,馬上見證奇蹟!上文說了,knockout最重要的意義在於雙向綁定,那麼如何實現我們的雙向綁定呢?答案就是監控屬性。

在knockout裡面,核心的有三個監控屬性:observables,dependentobservables,observablearray,observe的意思是觀察、觀測的意思,如果說成觀察屬性或觀測屬性感覺不太恰當,我們暫且叫監控屬性。

3.1、observables:監控屬性

我們將上面的範例改成這樣:
p>



index3

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>


<div> 
姓名:<label data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div>
//1.定义viewmodel var myviewmodel = { name: ko.observable("lilei"), profession: "软件工程师", }; //2.激活绑定 ko.applybindings(myviewmodel); $(function () { //注册文本框的textchange事件 $("#txt_testobservable").on("input", function () { myviewmodel.name($(this).val()); }); });

ko.observable("lilei") 這句話的意義是將viewmodel的name屬性加入成為監控屬性,一定name屬性變成監控屬性,神奇的事情就發生了,我們來看看當我們寫myviewmodel.的時候:

name由原來的屬性變成方法了,也就是說一旦加入了ko.observable(),那麼對應的屬性就會變成方法,那麼對於name的取值和賦值都需要使用myviewmodel.name()來處理。

程式碼釋疑:很顯然myviewmodel.name($(this).val()); 這句話將目前文字方塊的值賦給了name屬性,由於介面綁定了name屬性,所以label裡面的值也跟著改變了。或者你會說,這個使用textchange事件也可以做到的,只要將目前文字方塊的值賦給label標籤,也可以達到這個效果,這個不算什麼。確實,你的寫法也可以達到目的,但是我們的監控屬性的意義在於,任何地方改變了name的值,介面都會隨之變化,而不用每個地方去給label標籤賦值,js裡面只需要把關注點方法myviewmodel.name()上面即可。是不是很厲害~~

3.2、dependentobservables:監控依賴屬性

如果看了上面的監控屬性還沒過癮?下面再來看看監控依賴屬性的使用。

我們將程式碼再改下看看:



index3

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>


  姓名: 职业: 描述:
//1.定义viewmodel var myviewmodel = { name: ko.observable("lilei"), profession: ko.observable("软件工程师"), }; myviewmodel.des = ko.dependentobservable(function () { return "本人姓名——" + myviewmodel.name() + ",职业——" + myviewmodel.profession(); }); //2.激活绑定 ko.applybindings(myviewmodel);

程式碼釋疑:透過新增監控依賴屬性ko.dependentobservable() 將des屬性的值能同時監控到name和profession兩個的變化,其中任何一個發生變化,des綁定的標籤都會觸發改變,這樣做的最大好處就是避免了我們js去操作dom的麻煩,有點意思吧。

3.3、observablearray;監控陣列

除了上面兩種,ko也支援對陣列物件的監控。讓我們來看一個例子:



index3

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>


var deptarr = ko.observablearray([ { id: 1, name: '研发部' }, { id: 2, name: '行政部' }, { id: 3, name: '人事部' } ]); var viewmodel = { deptarr: deptarr, }; ko.applybindings(viewmodel); var i=4; $(function () { $("#btn_test").on("click", function () { deptarr.push({ id: i++, name: $("#txt_testobservable").val() }); }); });

程式碼釋疑:以上透過ko.observablearray()這個方法增加了對數組物件的監控,也就是說,js裡面任何地方只要對deptarr數組物件做了數組的改變,都會觸發ui給予對應。要注意的一點是,監控陣列其實是監控的陣列物件本身,對於陣列物件裡面的子物件屬性發生變化,是無法監控到的。例如我們將點擊事件改成這樣:

$(function () {
$("#btn_test").on("click", function () {
deptarr[1].name = "aaa";
});
});

由此說明數組監控實際上監控的是數組物件本身,對於數組裡面元素的屬性變化不會監控。如果確實需要對資料裡面物件的屬性變化進行監控,則需要再對資料裡面物件屬性使用ko.observable(),兩者合併使用。有興趣的可以試試。

4、ko裡面常見的data-bind屬性

上文中,我們使用了多個data-bind屬性,那麼在knockout裡面,到底有多少個這種data-bind的屬性呢。這裡我們列出一些常用的屬性。

4.1、text和inputtext

text,顧名思義就是文字的意思,這個綁定屬性一般用於

等標籤顯示文本,當然,如果你願意,任何標籤都可以使用這個綁定。它是使用基本上沒什麼好說的。如果沒有使用ko.observable(),則是靜態綁定,否則是動態綁定。

inputtext,input標籤的文本,相當於input標籤的value屬性。

  <div> 
姓名:<label data-bind="text:name"></label><br />
职业:<input type="text" data-bind="textinput:profession" />
</div> 
     //1.定义viewmodel
var myviewmodel = {
name: ko.observable("lilei"),
profession: "软件工程师",
};
//2.激活绑定
ko.applybindings(myviewmodel);

4.2、value

這個綁定屬性一般用於input標籤,和上面的inputtext基本上相似。只不過value更加規範。

和value一起使用的還有一個參數valueupdate,它表示介面做一個什麼操作的時候更新該value。 valueupdate主要取值有change/keyup/keypress/afterkeydown等。分別表示文字變化、鍵盤縮起、鍵盤按下、鍵盤按下之後等操作時候更新value對應的viewmodel的值。

姓名:
<input type="text" data-bind="value:name,valueupdate:'keyup'" /><br /> 
    var myviewmodel = {
name: ko.observable("lilei"),
};//2.激活绑定
ko.applybindings(myviewmodel);

上述程式碼表示鍵盤收起的時候更新文字方塊的value屬性和myviewmodel的name屬性。

4.3、checked

checked綁定一般用於checkbox、radio等可以選取的表單元素,它對應的值是bool型別。和value的用法基本上相似,就不做重複說明。

4.4、enable

enable綁定一般用於是否啟用標籤元素,一般用於表單元素的啟用和禁用。和disabled相反,對應的值也是bool型別。

<div>
<input type="text" data-bind="enable:ismen"/>
</div>
<script type="text/javascript">
//1.定义viewmodel
var myviewmodel = {
name: ko.observable("lilei"),
profession: ko.observable("软件工程师"),
age: ko.observable(40),
ismen:ko.observable(true)
};
//2.激活绑定
ko.applybindings(myviewmodel);
myviewmodel.ismen(false);
</script>

由於ismen屬性變成了false,所有對應的文字方塊都會顯示停用狀態。

4.5、disabled

和enable相反,用法和enable類似。

4.6、options

上文中在使用select的綁定時候使用過options,它表示select標籤的option的集合,對應的值為一個數組,表示這個下拉框的資料來源。可以使用observablearray啟用對這個資料來源的監控。用法見上面。

4.7、html

text綁定其實就是標籤innertext的設定和值,那麼同理,html綁定也是innerhtml的設定和取值。它對應的值為一段html標籤。

4.8、css

css綁定是新增或刪除一個或多個樣式(class)到dom元素上。使用格式:

<style type="text/css">
.testbold {
background-color:powderblue;
}
</style> 
<div data-bind="css:{testbold:myviewmodel.name()=='lilei'}">aaaa</div> 
var myviewmodel = {
name: ko.observable("lilei"),
profession: ko.observable("软件工程师"),
age:ko.observable(40)
};

該div會顯示背景色。

如果需要增加或移除多個樣式,只要稍微改下即可,例如:

<div data-bind="css:{testbold:myviewmodel.name()=='lilei',testborder:myviewmodel.profession()=='php工程师'}">aaaa</div>

4.9、style

如果css綁定的作用是在標籤動態上加入或移除class樣式,那麼style綁定的作用就是想標籤動態新增或移除某一個樣式。例如:

<div data-bind="css:{background-color:myviewmodel.name()=='lilei'?'red':'white'}">aaaa</div>

如果是新增或移除多個,同css綁定的用法

4.10、attr

attr綁定主要用於在標籤上新增移除某一個或多個屬性(包括自訂屬性),永和和css類似。

4.11、click

click綁定表示在對應的dom元素上面新增點擊事件的執行方法。可以在任意元素上面使用。

<div>
<input type="button" value="测试click绑定" data-bind="click:clickfunc" />
</div> 
    var myviewmodel = {
clickfunc:function(){
alert($(event.currenttarget).val());
}
};
ko.applybindings(myviewmodel);

event.currenttarget表示目前點選的dom元素。有時為了簡便,我們直接使用匿名函數的方式綁定,例如:

<div>
<input type="button" value="测试click绑定" data-bind="click:function(){
alert('点击了');
}" />
</div>

但這種將js揉到html裡面的寫法讓博主難以接受,並且覺得維護起來相對不方便,尤其是點擊事件裡面的邏輯略複雜時。所以,如非必須,不建議直接寫這種匿名函數的方式。

4.12、其他

關於data-bind的所有綁定,可以看官網上面的介紹,這裡就不一一列舉了。需要用的時候去官網上查下來就好了。看看官網上面列舉的所有綁定

5、json物件和監控屬性的轉換及關係

我們知道,為了避免不同語言直接的展現方式,一般情況下我們前端和後端交互的時候統一使用json格式的數據,我們透過http請求從後端取到的資料模型,而要使用我們的ko的一些特性,必須將這些普通的資料模型轉換成ko的監控屬性;反過來,我們使用ko的監控屬性,有時需要把這些屬性轉換為普通的json資料傳到後台,那麼要如何實現這個轉換呢?

5.1、json物件轉換成viewmodel

例如我們從後台取到一個json對象,然後把它變成到我們的viewmodel,然後綁定到我們的介面dom。

$.ajax({
url: "/home/getdata",
type: "get",
data: {},
success: function (data, status) {
var ojson = data;
}
});

我們發送一個請求到後端,取到一個json對象,賦值到ojson,然後我們把ojson轉換成viewmodel,最直覺的方式就是手動轉換了。例如我們可以這樣:

    var myviewmodeljson = {
deptname: ko.observable(),
deptlevel: ko.observable(),
deptdesc:ko.observable()
};
ko.applybindings(myviewmodeljson);

然後在ajax請求的success裡面

success: function (data, status) {
var ojson = data;
myviewmodeljson.deptname(ojson.deptname);
myviewmodeljson.deptlevel(ojson.detplevel);
myviewmodeljson.deptdesc(ojson.deptdesc);
}

這樣,透過手動綁定,實現了json物件到viewmodel的綁定。這樣做的好處就是靈活,壞處顯而易見,手工程式碼量太大。

還好,有我們萬能的開源,總有人想到更好的辦法,我們使用knockout.mapping元件就能很好地幫助我們介面json物件到viewmodel的轉換。

knockout.mapping開源位址:下載

下面來簡單看看它如何使用,還是上面的例子,我們不用實作定義任何viewmodel,首先需要引用knockout.mapping.js

<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>

注意:這裡knock.mapping-lastest.js必須放在knockout-3.4. 0.min.js的後面,否則呼叫不到ko.mapping。

然後直接在success函數裡面這樣使用

         success: function (data, status) {
var myviewmodeljson2 = ko.mapping.fromjs(data);
ko.applybindings(myviewmodeljson2);
}

程式碼釋疑:透過ajax請求從後台取到的json對象,透過ko.mapping.fromjs(),很方便地將其轉換成了viewmodel,是不是猴犀利!當然除了這種用法,還可以更新已經存在viewmodel,使用如下:

    var myviewmodeljson = {
deptname: ko.observable(),
deptlevel: ko.observable(),
deptdesc:ko.observable()
};
ko.applybindings(myviewmodeljson);
$(function () {
$.ajax({
url: "/home/getdata",
type: "get",
data: {},
success: function (data, status) {
ko.mapping.fromjs(data, myviewmodeljson)
}
});
});

在success裡面,依照data的值去更新myviewmodeljson這個viewmodel。

5.2、viewmodel轉換成json物件

上面說了json物件轉換為viewmodel,那麼反過來,如果我們需要將viewmodel轉換為json物件傳遞到後端,該怎麼辦呢?

knockout裡面提供了兩個方法:

•ko.tojs( ):將viewmodel轉換為json物件
•ko.tojson():將viewmodel轉換為序列化過的json string。

例如我們的程式碼如下: 

$(function () {
var ojson1 = ko.tojs(myviewmodeljson);
var ojson2 = ko.tojson(myviewmodeljson);
});
var myviewmodeljson = {
deptname: ko.observable("研发部"),
deptlevel: ko.observable("2"),
deptdesc: ko.observable("开发一伙人")
};
ko.applybindings(myviewmodeljson);

那麼我們來監控下ojson1和ojson2的值

程式碼釋疑:這裡要說明一點的是,這兩個方法是ko自帶的,並不需要mapping元件的支持。

6、建立自己的data-bind屬性

上面講了那麼多,都是介紹knockout裡面的一些綁定和監控,那麼,有些時候,我們需要自訂我們的data-bind,型如:

在knockout裡面,提供了ko.bindinghandlers屬性,用於自訂data-bind屬性,它的語法如下:

ko.bindinghandlers.myselect = {
init: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
},
update: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
}
};

就這樣申明一下,然後在我們的html標籤裡面就可以使用自訂data-bind了。

<div> 
<select data-bind="myselect:$root">
<option id="1">研发部</option>
<option id="2">人事部</option>
<option id="3">行政部</option>
</select>
</div>

myselect就是我們自訂的綁定屬性,$root暫且可以理解為初始化(雖然這樣解釋並不嚴謹,如果有更合理的解釋歡迎指正)。

程式碼釋疑:透過上面的ko.bindinghandlers就能簡單實作自訂綁定屬性,需要說明兩點:

•init,顧名思義初始化自訂綁定定,它裡麵包含多個參數,一般使用較多的是前兩個參數,第一個參數表示初始化自訂綁定的dom元素,第二個參數一般用來傳遞初始化的參數。
•update,更新回調,當對應的監控屬性改變時,會進入這個方法。如果不需要回調,此方法可以不聲明。

在此部落客就結合原來分享過的一個下拉框組件mutiselect來簡單說明下自訂綁定的使用。

6.1、最簡單的mutiselect

一般情況下,如果我們需要使用ko去封裝一些通用元件,就需要用到我們的ko.bindinghandlers,下面部落客就結合mutiselect組件來說說如何使用。

先宣告自訂的ko.bindinghandlers,在init方法裡面初始化我們的select標籤

ko.bindinghandlers.myselect = {
init: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
$(element).multiselect();
},
update: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
}
};

然後在頁面標籤裡面使用

<div style="text-align:center;"> 
<select data-bind="myselect:$root">
<option id="1">研发部</option>
<option id="2">人事部</option>
<option id="3">行政部</option>
</select>
</div>

最後第三部,啟動綁定

$(function () {
var multiselect = {};
ko.applybindings(multiselect);
});

如果不需要傳遞參數,這裡只需要綁定一個空的viewmodel即可。有人疑惑了,第三部感覺沒啥實際意義。部落客的理解是,dom元素需要使用data-bind去綁定數據,必須要啟用ko的綁定,也就是這裡的ko.applybindings()。

第一步還是自訂ko.bindinghandlers

ko.bindinghandlers.myselect = {
init: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
var oparam = valueaccessor();
$(element).multiselect(oparam);
},
update: function (element, valueaccessor, allbindingsaccessor, viewmodel) {
}
};

第二步和上方相同,在html標籤裡面使用這個自訂綁定。

第三步,在啟動綁定的時候傳入參數

$(function () {
var MultiSelect = {
enableClickableOptGroups: true,//收起分组
onChange: function (option, checked) {
alert("选择改变");
}
};
ko.applyBindings(MultiSelect);
});

透過這三步驟即可將參數傳到我們的mutiselect的初始化裡面:

程式碼釋疑:init事件的第二個參數,我們說了,它主要作用是取得我們viewmodel裡面傳過來的參數,只不過這裡要把它當做方法使用,為什麼會這麼用,還有待研究!

二、第一個增刪改查實例

至此基礎的東西終於是鋪墊完了,本來打算一篇搞定的,可以沒料到基礎的東西展開來這麼多篇幅!增刪改查的範例放到下篇bootstraptable與knockoutjs結合實作增刪改查功能【二】,歡迎學習交流,當然也歡迎推薦!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript的角色:使網絡交互和動態JavaScript的角色:使網絡交互和動態Apr 24, 2025 am 12:12 AM

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python vs. JavaScript:比較用例和應用程序Python vs. JavaScript:比較用例和應用程序Apr 21, 2025 am 12:01 AM

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C/C在JavaScript口譯員和編譯器中的作用C/C在JavaScript口譯員和編譯器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在行動中:現實世界中的示例和項目JavaScript在行動中:現實世界中的示例和項目Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

了解JavaScript引擎:實施詳細信息了解JavaScript引擎:實施詳細信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境