ue 是一套用于構(gòu)建用戶界面的漸進式框架,與其它大型 JS 框架不同,Vue 被設(shè)計為可以自底向上逐層應(yīng)用,更易上手,還便于與第三方庫或既有項目整合,因此,Vue 完全能夠為復(fù)雜的單頁應(yīng)用提供驅(qū)動。
2020年09月18日,Vue.js 3.0 正式發(fā)布,作者尤雨溪將其描述為:更快、更小、更易于維護。
本次發(fā)布, Vue 框架本身迎來了多項更新,如 Vue 此前的反應(yīng)系統(tǒng)是使用 Object.defineProperty 的 getter 和 setter。 但是,在 Vue 3中,將使用 ES2015 Proxy 作為其觀察者機制,這樣做的好處是消除了以前存在的警告,使速度加倍,并節(jié)省了一半的內(nèi)存開銷。
除了基于 Proxy 的觀察者機制,Vue 3的其他新特性還包括:
1. Performance(性能提升)
在Vue 2中,當某個DOM需要更新時,需要遍歷整個虛擬DOM樹才能判斷更新點。而在Vue 3中,無需此項操作,僅需通過靜態(tài)標記,對比虛擬節(jié)點上帶有patch flag的節(jié)點,即可定位更新位置。
對比Vue 2和Vue 3的性能差異,官方文檔中給出了具體數(shù)據(jù)說明:
2. Composition API(組合API)
Vue 2中有data、methods、mounted等存儲數(shù)據(jù)和方法的對象,我們對此應(yīng)該不陌生了。比如說要實現(xiàn)一個輪播圖的功能,首先需要在 data 里定義與此功能相關(guān)的數(shù)據(jù),在 methods 里定義該功能的方法,在mounted里定義進入頁面自動開啟輪播的代碼…… 有一個顯而易見的問題,就是同一個功能的代碼卻要分散在頁面的不同地方,維護起來會相當麻煩。
為了解決上述問題,Vue 3推出了具備清晰的代碼結(jié)構(gòu),并可消除重復(fù)邏輯的 Composition API,以及兩個全新的函數(shù)setup和ref。
Setup 函數(shù)可將屬性和方法返回到模板,在組件初始化的時候執(zhí)行,其效果類似于Vue 2中的beforeCreate 和 created。如果想使用setup里的數(shù)據(jù),需要將值return出來,沒有從setup函數(shù)返回的內(nèi)容在模板中不可用。
Ref函數(shù)的作用是創(chuàng)建一個引用值,主要是對String、Number、Boolean的數(shù)據(jù)響應(yīng)做引用。
相對于Vue 2,Vue 3的生命周期函數(shù)也發(fā)生了變更,如下所示:
需要注意的是,Vue 2使用生命周期函數(shù)時是直接在頁面中寫入生命周期函數(shù),而在Vue 3則直接引用即可:
import {reactive, ref, onMounted} from 'vue'
3. Tree shaking support(按需打包模塊)
有人將"Tree shaking" 稱之為"搖樹優(yōu)化",其實就是把無用的模塊進行"剪枝",剪去沒有用到的API,因此"Tree shaking"之后,打包的體積將大幅度減少。
官方將Vue 2和Vue 3進行了對比,Vue 2若只寫了Hello World,且沒有用到任何的模塊API,打包后的大小約為32kb,而Vue 3 打包后僅有13.5kb。
4. 全新的腳手架工具:Vite
Vite 是一個由原生 ESM 驅(qū)動的 Web 開發(fā)構(gòu)建工具。在開發(fā)環(huán)境下基于瀏覽器原生 ES imports 開發(fā),在生產(chǎn)環(huán)境下基于 Rollup 打包。
和 Webpack相比,具有以下特點:
由于完全跳過了打包這個概念,Vite的出現(xiàn)大大的撼動了Webpack的地位,且真正做到了服務(wù)器隨起隨用。看來,連尤大神都難逃"真香"理論。
Vite究竟有什么魔力?不妨讓我們通過實際搭建一款基于Vue 3 組件的表格編輯系統(tǒng),親自體驗一把。
使用 Vite 初始化一個 Vue 3 項目
1. 執(zhí)行代碼:
$ npm init vite-app <project-name>
$ cd <project-name> //進入項目目錄
$ npm install //安裝項目所需依賴
$ npm run dev //啟動項目
我們來看下生成的代碼, 因為 vite 會盡可能多地鏡像 vue-cli 中的默認配置, 所以,這段代碼看上去和 vue-cli 生成的代碼沒有太大區(qū)別。
├── index.html
├── package.json
├── public
│ └── favicon.ico
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
├── index.css
└── main.js
2. 執(zhí)行下列命令:
此時如果不通過 npm run dev 來啟動項目,而是直接通過瀏覽器打開 index.html, 會看到下面的報錯:
報錯的原因:瀏覽器的 ES module 是通過 http 請求拿到模塊的,所以 vite 的一個任務(wù)就是啟動一個 web server 去代理這些模塊,在 vite 里是借用了 koa 來啟動的服務(wù)。
export function createServer(config: ServerConfig): Server {
// ...
const app = new Koa<State, Context>()
const server = resolveServer(config, app.callback())
// ...
const listen = server.listen.bind(server)
server.listen = (async (...args: any[])=> {
if (optimizeDeps.auto !== false) {
await require('../optimizer').optimizeDeps(config)
}
return listen(...args)
}) as any
return server
}
由于瀏覽器中的 ESM 是獲取不到導(dǎo)入的模塊內(nèi)容的,需要借助Webpack 等工具,如果我們沒有引用相對路徑的模塊,而是引用 node_modules,并直接 import xxx from 'xxx',瀏覽器便無法得知你項目里有 node_modules,只能通過相對路徑或者絕對路徑去尋找模塊。
這便是vite 的實現(xiàn)核心:攔截瀏覽器對模塊的請求并返回處理后的結(jié)果(關(guān)于vite 的實現(xiàn)機制,文末會深入講解)。
3. 生成項目結(jié)構(gòu):
入口 index.html 和 main.js 代碼結(jié)構(gòu)為:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
// main.js
// 只是引用的是最新的 vue3 語法,其余相同
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
4. 進入項目目錄:cd myVue3
5. 安裝相關(guān)模塊:npm install
6. 下載模塊:
7. 啟動項目:npm run dev
8. 進入地址,當我們看到這個頁面時,說明項目已經(jīng)成功啟動了。
1. /@module/ 前綴
對比工程下的 main.js 和開發(fā)環(huán)境下實際加載的 main.js,可以發(fā)現(xiàn)代碼發(fā)生了變化。
工程下的 main.js:
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
實際加載的 main.js:
import { createApp } from '/@modules/vue.js'
import App from '/src/App.vue'
import '/src/index.css?import'
createApp(App).mount('#app')
為了解決 import xxx from 'xxx' 報錯的問題,vite 對這種資源路徑做了統(tǒng)一處理,即添加一個/@module/前綴。
在 src/node/server/serverPluginModuleRewrite.ts 源碼的 koa 中間件里可以看到 vite 對 import 做了一層處理,其過程如下:
2. 支持 /@module/
在 /src/node/server/serverPluginModuleResolve.ts 里可以看到大概的處理邏輯:
3. 文件編譯
通過前文,我們知道了 js module 的處理過程,對于vue、css、ts等文件,其又是如何處理的呢?
以 vue 文件為例,在 webpack 里使用 vue-loader 對單文件組件進行編譯,在這里 vite 同樣攔截了對模塊的請求并執(zhí)行了一個實時編譯。
通過工程下的 App.vue 和實際加載的 App.vue,便發(fā)現(xiàn)改變。
工程下的 App.vue:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3.0 + Vite" />
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';
export default {
name: 'App',
components: {
HelloWorld,
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
實際加載的 App.vue:
import HelloWorld from '/src/components/HelloWorld.vue';
const __script = {
name: 'App',
components: {
HelloWorld,
},
};
import "/src/App.vue?type=style&index=0&t=1592811240845"
import {render as __render} from "/src/App.vue?type=template&t=1592811240845"
__script.render = __render
__script.__hmrId = "/src/App.vue"
__script.__file = "/Users/wang/qdcares/test/vite-demo/src/App.vue"
export default __script
可見,一個 .vue 文件被拆成了三個請求(分別對應(yīng) script、style 和template) ,瀏覽器會先收到包含 script 邏輯的 App.vue 的響應(yīng),然后解析到 template 和 style 的路徑后,再次發(fā)起 HTTP 請求來請求對應(yīng)的資源,此時 Vite 對其攔截并再次處理后返回相應(yīng)的內(nèi)容。
// App.vue?type=style
import { updateStyle } from "/vite/hmr"
const css = "\n#app {\n font-family: Avenir, Helvetica, Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-align: center;\n color: #2c3e50;\n margin-top: 60px;\n}\n"
updateStyle("7ac74a55-0", css)
export default css
// App.vue?type=template
import {createVNode as _createVNode, resolveComponent as _resolveComponent, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock} from "/@modules/vue.js"
const _hoisted_1 = /*#__PURE__*/
_createVNode("img", {
alt: "Vue logo",
src: "/src/assets/logo.png"
}, null, -1 /* HOISTED */
)
export function render(_ctx, _cache) {
const _component_HelloWorld = _resolveComponent("HelloWorld")
return (_openBlock(),
_createBlock(_Fragment, null, [_hoisted_1, _createVNode(_component_HelloWorld, {
msg: "Hello Vue 3.0 + Vite"
})], 64 /* STABLE_FRAGMENT */
))
}
vite對于其他的類型文件的處理幾乎都是類似的邏輯,即根據(jù)請求的不同文件類型,做出不同的編譯處理結(jié)果。
歡迎點擊下方“了解更多”獲取更多技術(shù)詳情。
前一篇文章相同,使用同樣的Mapper、Interface、Service,修改Controller返回的數(shù)據(jù)格式,使用jQuery顯示表格。
一、Controller
package com.gl.controller;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.gl.entity.Grjbxx;
import com.gl.service.GrjbxxService;
import net.sf.json.JSONObject;
@Controller
public class GrjbxxController {
@Resource
GrjbxxService grjbxxService;
@ResponseBody
@GetMapping("/grjbxxlistjson")
public List<Grjbxx> getgrjbxx() {
List<Grjbxx> grjbxxs=grjbxxService.findAll();
return grjbxxs;
}
}
二、Thymeleaf模板引擎
exceljs是一個讀取,操作和編寫電子表格數(shù)據(jù)和樣式到XLSX和JSON,從Excel電子表格文件逆向工程設(shè)計的項目。之所以稱它最強,是因為它的功能強大,簡直就是專門為Excel打造的前端處理插件,到目前為止,筆者還尚未見過比這個更強大的前端插件,由于其強悍的前端處理能力,這就意味著有很多操作將減輕服務(wù)器端壓力,而且性能更加出色!
https://github.com/exceljs/exceljs
安裝我們當然是首選npm
npm install exceljs
var workbook=new Excel.Workbook();
workbook.creator='Me';
workbook.lastModifiedBy='Her';
workbook.created=new Date(1985, 8, 30);
workbook.modified=new Date();
workbook.lastPrinted=new Date(2016, 9, 27);
// 將工作簿日期設(shè)置為1904日期系統(tǒng)
workbook.properties.date1904=true;
“工作簿”視圖控制Excel在查看工作簿時打開多少個單獨的窗口。
workbook.views=[
{
x: 0, y: 0, width: 10000, height: 20000,
firstSheet: 0, activeTab: 1, visibility: 'visible'
}
]
var sheet=workbook.addWorksheet('My Sheet');
用addWorksheet函數(shù)的第二個參數(shù)設(shè)置工作表的選項。
// 創(chuàng)建一個紅色標簽顏色的工作表
var sheet=workbook.addWorksheet('My Sheet', {properties:{tabColor:{argb:'FFC0000'}}});
// 創(chuàng)建一個隱藏網(wǎng)格線的工作表
var sheet=workbook.addWorksheet('My Sheet', {properties: {showGridLines: false}});
// 創(chuàng)建一個第一行和列凍結(jié)的工作表
var sheet=workbook.addWorksheet('My Sheet', {views:[{xSplit: 1, ySplit:1}]});
使用工作表id從工作簿中刪除工作表。
// 創(chuàng)建工作表
var sheet=workbook.addWorksheet('My Sheet');
// 使用工作表ID刪除工作表
workbook.removeWorksheet(sheet.id)
// 迭代所有sheet
// 注意:workbook.worksheets.forEach仍然可以工作,但這個方式更好
workbook.eachSheet(function(worksheet, sheetId) {
// ...
});
// 按名稱獲取表格
var worksheet=workbook.getWorksheet('My Sheet');
// 按ID獲取表格
var worksheet=workbook.getWorksheet(1);
。。。。。。以上只是部分文檔中的介紹,感興趣的小伙伴可以移步Github直接查看詳細的文檔,完整功能了解可參考下一個標題
PS:提供了中文文檔
雖然以上功能還不能包括了Excel的所有功能,但也已經(jīng)相當?shù)呢S富了!
在之前的文章中曾介紹過另一個不錯的前端Excel插件,感興趣的可以去看一看,exceljs擁有這么豐富的功能,如果你想開發(fā)一個功能強大的Web電子表格,不妨多嘗試嘗試!
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。