vue導(dǎo)出報(bào)表至excel表格三種方式
1、序言
1.1、源碼
源碼在下方,復(fù)制運(yùn)行,安裝相應(yīng)的插件即可
1.2、坑
方式一、方式二安裝相同插件:
npm install xlsx xlsx-style file-saver
導(dǎo)入 xlsx-style 會(huì)報(bào)如下的錯(cuò)誤
解決辦法:
(1)去node_modules下面找到xlsx/dist/ 修改相應(yīng)配置,這樣非常不好,每次npm install,都要跑去node_modules下面修改,非常麻煩!
(2)新建vue.config.js,復(fù)制如下代碼,重啟項(xiàng)目即可
module.exports = { configureWebpack: (config) => { // 解決xlsx-style報(bào)錯(cuò)的問題 return { externals: [{ './cptable': 'var cptable' }] } } }
還有一個(gè)坑
解決辦法:
1.3、實(shí)現(xiàn)功能說明
未實(shí)現(xiàn):
(1)單元格樣式修改還未實(shí)現(xiàn),后期找到合適的方法會(huì)更新此博客
(2)不能導(dǎo)出圖片至excel表中,只把表格數(shù)據(jù)導(dǎo)出至excel表
(3)導(dǎo)出的excel報(bào)表沒有多個(gè)Sheet
已實(shí)現(xiàn):
(1)表格正常導(dǎo)出
(2)多級(jí)表頭導(dǎo)出
(3)單元格自定義內(nèi)容、合計(jì)行導(dǎo)出
2、方式一(xlsx)(不推薦)
2.1、工具方法
Export2Excel.js
export function export_json_to_excel({ multiHeader = [], // 第一行表頭 multiHeader2 = [], // 第二行表頭 data, filename, //文件名 merges = [], // 合并 bookType = 'xlsx' } = {}) { /* original data */ filename = filename || '列表'; data = [...data] data.unshift(multiHeader2) data.unshift(multiHeader) console.log('data:', data) var ws_name = "SheetJS"; var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); if (merges.length > 0) { if (!ws['!merges']) ws['!merges'] = []; merges.forEach(item => { ws['!merges'].push(XLSX.utils.decode_range(item)) }) } /* add worksheet to workbook */ wb.SheetNames.push(ws_name); wb.Sheets[ws_name] = ws; var wbout = XLSXStyle.write(wb, { bookType: bookType, bookSST: false, type: 'binary' }); saveAs(new Blob([s2ab(wbout)], { type: "application/octet-stream" }), `${filename}.${bookType}`); }
2.2、使用
// multiHeader: 一級(jí)表頭 // multiHeader2:二級(jí)表頭 // data:表格數(shù)據(jù) // merges:需要合并的單元格 // filename:導(dǎo)出的excel文件名 import('@/utils/Export2Excel').then((excel) => { excel.export_json_to_excel({ multiHeader, multiHeader2, data, merges, filename: '報(bào)表導(dǎo)出一', }); })
2.3、目標(biāo)效果
2.4、缺點(diǎn)
(1)沒有合計(jì)行
(2)表格插槽自定義的內(nèi)容,如添加的單位: kg、cm、歲不能一起導(dǎo)出來
(3)最痛苦的是多級(jí)表頭導(dǎo)出的時(shí)候還要一個(gè)個(gè)算單元格哪些需要合并、多級(jí)表頭數(shù)組的字段排放,字段少還好,多的時(shí)候就痛苦面具了!
3、方式二(xlsx結(jié)合dom)(推薦)
3.1、工具方法
Export2Excel.js
// 根據(jù)dom導(dǎo)出表格 export function exportToExcel(idSelector, fileName, titleNum = 1) { // 設(shè)置導(dǎo)出的內(nèi)容是否只做解析,不進(jìn)行格式轉(zhuǎn)換 false:要解析, true:不解析 const xlsxParam = { raw: true } let table = document.querySelector(idSelector).cloneNode(true); // 因?yàn)閑lement-ui的表格的fixed屬性導(dǎo)致多出一個(gè)table,會(huì)下載重復(fù)內(nèi)容,這里刪除掉 if (table.querySelector('.el-table__fixed-right')) table.removeChild(table.querySelector('.el-table__fixed-right')); if (table.querySelector('.el-table__fixed')) table.removeChild(table.querySelector('.el-table__fixed')); const wb = XLSX.utils.table_to_book(table, xlsxParam) let range = XLSX.utils.decode_range(wb.Sheets['Sheet1']['!ref']); let cWidth = []; for (let C = range.s.c; C < range.e.c; ++C) { //SHEET列 let len = 100; //默認(rèn)列寬 let len_max = 400; //最大列寬 for (let R = range.s.r; R <= range.e.r; ++R) { //SHEET行 let cell = { c: C, r: R }; //二維 列行確定一個(gè)單元格 let cell_ref = XLSX.utils.encode_cell(cell); //單元格 A1、A2 if (wb.Sheets['Sheet1'][cell_ref]) { // if (R == 0){ if (R < titleNum) { wb.Sheets['Sheet1'][cell_ref].s = { //設(shè)置第一行單元格的樣式 style alignment: { horizontal: 'center', vertical: 'center', }, }; } else { wb.Sheets['Sheet1'][cell_ref].s = { alignment: { horizontal: 'center', vertical: 'center', }, }; } //動(dòng)態(tài)自適應(yīng):計(jì)算列寬 let va = JSON.parse(JSON.stringify(wb.Sheets['Sheet1'][cell_ref].v)); var card1 = JSON.parse(JSON.stringify(va)).match(/[\u4e00-\u9fa5]/g); //匹配中文 var card11 = ""; if (card1) { card11 = card1.join("") } var card2 = JSON.parse(JSON.stringify(va)).replace(/([^\u0000-\u00FF])/g, ""); //剔除中文 let st = 0; if (card11) { // st += card11.length * 16 //中文字節(jié)碼長度 st += card11.length * 20 //中文字節(jié)碼長度 } if (card2) { // st += card2.length * 8 //非中文字節(jié)碼長度 st += card2.length * 10 //非中文字節(jié)碼長度 } if (st > len) { len = st; } } } if (len > len_max) {//最大寬度 len = len_max; } cWidth.push({ 'wpx': len }); //列寬 } wb.Sheets['Sheet1']['!cols'] = cWidth const wbout = XLSXStyle.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' }) try { saveAs(new Blob([s2ab(wbout)], { type: '' }), `${fileName}.xlsx`) } catch (e) { if (typeof console !== 'undefined') { console.log(e, wbout) } } return wbout }
3.2、使用
import { exportToExcel } from '@/utils/Export2Excel' methods: { // 方式二導(dǎo)出報(bào)表 handleExport2() { // exportToExcel(表格id選擇器, 導(dǎo)出文件名稱); exportToExcel('#table', '報(bào)表導(dǎo)出二'); }, }
3.2、效果
除了合計(jì)行有點(diǎn)小小的瑕疵,其他部分非常完美了,代碼少,實(shí)現(xiàn)的功能又多,相當(dāng)于導(dǎo)出el-table了!
4、方式三(vue-json-excel)(不推薦)
# 安裝插件
npm i vue-json-excel
# 插件官網(wǎng):GitHub - jecovier/vue-json-excel
4.1、使用
字段說明
字段名稱 | 字段類型 | 字段說明 |
data | Array | 表格數(shù)據(jù) |
fields | Object | 不填寫的話,導(dǎo)出的excel表頭名稱為 data數(shù)據(jù)里面的屬性名稱,其實(shí)就是字段名稱映射成中文 |
type | string | 導(dǎo)出的文件類型,默認(rèn)xls |
name | string | 導(dǎo)出的文件名稱 |
title | string | excel表格標(biāo)題 |
main.js
import Vue from 'vue' import App from './App.vue' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import JsonExcel from "vue-json-excel"; Vue.component("downloadExcel", JsonExcel); Vue.use(ElementUI); new Vue({ render: h => h(App), }).$mount('#app')
頁面使用
每個(gè)字段可以自定義單元格格式化輸出內(nèi)容,比如加上單位
4.2、效果
4.3、缺點(diǎn)
(1)多級(jí)表頭導(dǎo)不出來,官方文檔寫的不夠詳細(xì)
(2)沒有合計(jì)行
(3)配置稍顯繁瑣
5、源碼
vue.config.js
module.exports = { configureWebpack: (config) => { // 解決xlsx-style報(bào)錯(cuò)的問題 return { externals: [{ './cptable': 'var cptable' }] } } }
main.js
import Vue from 'vue' import App from './App.vue' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import JsonExcel from "vue-json-excel"; Vue.component("downloadExcel", JsonExcel); Vue.use(ElementUI); Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app')
App.vue
<template> <div id="app"> <div style="display: flex; justify-content: center;"> <el-button type="success" @click="handleExport">導(dǎo)出一</el-button> <el-button type="primary" @click="handleExport2">導(dǎo)出二</el-button> <download-excel :data="tableData" :fields="fields" name="報(bào)表三"> <el-button type="warning">導(dǎo)出三</el-button> </download-excel> </div> <el-table :data="tableData" id="table" ref="table" border style="width: 100%; margin-top: 20px;" show-summary> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column label="個(gè)人信息" align="center"> <el-table-column prop="height" label="身高"> <template slot-scope="{row}"> {{ row.height + 'cm' }} </template> </el-table-column> <el-table-column prop="weight" label="體重"> <template slot-scope="{row}"> {{ row.weight + 'kg' }} </template> </el-table-column> <el-table-column prop="age" label="年齡"> <template slot-scope="{row}"> {{ row.age + '歲' }} </template> </el-table-column> </el-table-column> </el-table> </div> </template> <script> import { exportToExcel } from '@/utils/Export2Excel' export default { name: 'App', components: { }, data() { return { tableData: [{ date: '2016-05-03', name: '王大虎', age: 20, weight: 70, height: 188 }, { date: '2016-05-02', name: '王二虎', age: 18, weight: 60, height: 177 }, { date: '2016-05-04', name: '王小虎', age: 16, weight: 50, height: 166 }], fields: { '日期': 'date', '姓名': 'name', '身高': { field: 'height', callback: (value) => { return `${value} cm`; }, }, '體重': { field: 'weight', callback: (value) => { return `${value} kg`; }, }, '年齡': { field: 'age', callback: (value) => { return `${value} 歲`; }, }, } } }, methods: { // 方式一導(dǎo)出報(bào)表 handleExport() { // 一級(jí)表頭 const multiHeader = [ "日期", "姓名", "個(gè)人信息", ]; // 二級(jí)表頭 const multiHeader2 = [ "", "", "身高", "體重", "年齡", ]; // 根據(jù)Excel確定要合并的單元格 const merges = [ "A1:A2", "B1:B2", "C1:E1", ]; // const header = this.$refs.table.columns.map(item => item.label) const columns = this.$refs.table.columns.map(item => item.property) const data = this.tableData.map(v => columns.map(j => v[j])); import('@/utils/Export2Excel').then((excel) => { excel.export_json_to_excel({ multiHeader, multiHeader2, data, merges, filename: '報(bào)表導(dǎo)出一', }); }) }, // 方式二導(dǎo)出報(bào)表 handleExport2() { exportToExcel('#table', '報(bào)表導(dǎo)出二'); }, } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } </style>
utils/Export2Excel.js
/* eslint-disable */ import { saveAs } from 'file-saver' import * as XLSX from 'xlsx' import * as XLSXStyle from "xlsx-style"; function datenum(v, date1904) { if (date1904) v += 1462; var epoch = Date.parse(v); return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); } function sheet_from_array_of_arrays(data, opts) { var ws = {}; var range = { s: { c: 10000000, r: 10000000 }, e: { c: 0, r: 0 } }; for (var R = 0; R != data.length; ++R) { for (var C = 0; C != data[R].length; ++C) { if (range.s.r > R) range.s.r = R; if (range.s.c > C) range.s.c = C; if (range.e.r < R) range.e.r = R; if (range.e.c < C) range.e.c = C; var cell = { v: data[R][C] }; if (cell.v == null) continue; var cell_ref = XLSX.utils.encode_cell({ c: C, r: R }); if (typeof cell.v === 'number') cell.t = 'n'; else if (typeof cell.v === 'boolean') cell.t = 'b'; else if (cell.v instanceof Date) { cell.t = 'n'; cell.z = XLSX.SSF._table[14]; cell.v = datenum(cell.v); } else cell.t = 's'; ws[cell_ref] = cell; } } if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range); return ws; } function Workbook() { if (!(this instanceof Workbook)) return new Workbook(); this.SheetNames = []; this.Sheets = {}; } function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; return buf; } export function export_json_to_excel({ multiHeader = [], // 第一行表頭 multiHeader2 = [], // 第二行表頭 data, filename, //文件名 merges = [], // 合并 bookType = 'xlsx' } = {}) { /* original data */ filename = filename || '列表'; data = [...data] data.unshift(multiHeader2) data.unshift(multiHeader) console.log('data:', data) var ws_name = "SheetJS"; var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); if (merges.length > 0) { if (!ws['!merges']) ws['!merges'] = []; merges.forEach(item => { ws['!merges'].push(XLSX.utils.decode_range(item)) }) } /* add worksheet to workbook */ wb.SheetNames.push(ws_name); wb.Sheets[ws_name] = ws; var wbout = XLSXStyle.write(wb, { bookType: bookType, bookSST: false, type: 'binary' }); saveAs(new Blob([s2ab(wbout)], { type: "application/octet-stream" }), `${filename}.${bookType}`); } // 根據(jù)dom導(dǎo)出表格 export function exportToExcel(idSelector, fileName, titleNum = 1) { // 設(shè)置導(dǎo)出的內(nèi)容是否只做解析,不進(jìn)行格式轉(zhuǎn)換 false:要解析, true:不解析 const xlsxParam = { raw: true } let table = document.querySelector(idSelector).cloneNode(true); // 因?yàn)閑lement-ui的表格的fixed屬性導(dǎo)致多出一個(gè)table,會(huì)下載重復(fù)內(nèi)容,這里刪除掉 if (table.querySelector('.el-table__fixed-right')) table.removeChild(table.querySelector('.el-table__fixed-right')); if (table.querySelector('.el-table__fixed')) table.removeChild(table.querySelector('.el-table__fixed')); const wb = XLSX.utils.table_to_book(table, xlsxParam) let range = XLSX.utils.decode_range(wb.Sheets['Sheet1']['!ref']); let cWidth = []; for (let C = range.s.c; C < range.e.c; ++C) { //SHEET列 let len = 100; //默認(rèn)列寬 let len_max = 400; //最大列寬 for (let R = range.s.r; R <= range.e.r; ++R) { //SHEET行 let cell = { c: C, r: R }; //二維 列行確定一個(gè)單元格 let cell_ref = XLSX.utils.encode_cell(cell); //單元格 A1、A2 if (wb.Sheets['Sheet1'][cell_ref]) { // if (R == 0){ if (R < titleNum) { wb.Sheets['Sheet1'][cell_ref].s = { //設(shè)置第一行單元格的樣式 style alignment: { horizontal: 'center', vertical: 'center', }, }; } else { wb.Sheets['Sheet1'][cell_ref].s = { alignment: { horizontal: 'center', vertical: 'center', }, }; } //動(dòng)態(tài)自適應(yīng):計(jì)算列寬 let va = JSON.parse(JSON.stringify(wb.Sheets['Sheet1'][cell_ref].v)); var card1 = JSON.parse(JSON.stringify(va)).match(/[\u4e00-\u9fa5]/g); //匹配中文 var card11 = ""; if (card1) { card11 = card1.join("") } var card2 = JSON.parse(JSON.stringify(va)).replace(/([^\u0000-\u00FF])/g, ""); //剔除中文 let st = 0; if (card11) { // st += card11.length * 16 //中文字節(jié)碼長度 st += card11.length * 20 //中文字節(jié)碼長度 } if (card2) { // st += card2.length * 8 //非中文字節(jié)碼長度 st += card2.length * 10 //非中文字節(jié)碼長度 } if (st > len) { len = st; } } } if (len > len_max) {//最大寬度 len = len_max; } cWidth.push({ 'wpx': len }); //列寬 } wb.Sheets['Sheet1']['!cols'] = cWidth const wbout = XLSXStyle.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' }) try { saveAs(new Blob([s2ab(wbout)], { type: '' }), `${fileName}.xlsx`) } catch (e) { if (typeof console !== 'undefined') { console.log(e, wbout) } } return wbout }
utils/Blob.js
/* eslint-disable */ /* Blob.js * A Blob implementation. * 2014-05-27 * * By Eli Grey, http://eligrey.com * By Devin Samarin, https://github.com/eboyjr * License: X11/MIT * See LICENSE.md */ /*global self, unescape */ /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, plusplus: true */ /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ (function (view) { "use strict"; view.URL = view.URL || view.webkitURL; if (view.Blob && view.URL) { try { new Blob; return; } catch (e) {} } // Internally we use a BlobBuilder implementation to base Blob off of // in order to support older browsers that only have BlobBuilder var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) { var get_class = function(object) { return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; } , FakeBlobBuilder = function BlobBuilder() { this.data = []; } , FakeBlob = function Blob(data, type, encoding) { this.data = data; this.size = data.length; this.type = type; this.encoding = encoding; } , FBB_proto = FakeBlobBuilder.prototype , FB_proto = FakeBlob.prototype , FileReaderSync = view.FileReaderSync , FileException = function(type) { this.code = this[this.name = type]; } , file_ex_codes = ( "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" ).split(" ") , file_ex_code = file_ex_codes.length , real_URL = view.URL || view.webkitURL || view , real_create_object_URL = real_URL.createObjectURL , real_revoke_object_URL = real_URL.revokeObjectURL , URL = real_URL , btoa = view.btoa , atob = view.atob , ArrayBuffer = view.ArrayBuffer , Uint8Array = view.Uint8Array ; FakeBlob.fake = FB_proto.fake = true; while (file_ex_code--) { FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; } if (!real_URL.createObjectURL) { URL = view.URL = {}; } URL.createObjectURL = function(blob) { var type = blob.type , data_URI_header ; if (type === null) { type = "application/octet-stream"; } if (blob instanceof FakeBlob) { data_URI_header = "data:" + type; if (blob.encoding === "base64") { return data_URI_header + ";base64," + blob.data; } else if (blob.encoding === "URI") { return data_URI_header + "," + decodeURIComponent(blob.data); } if (btoa) { return data_URI_header + ";base64," + btoa(blob.data); } else { return data_URI_header + "," + encodeURIComponent(blob.data); } } else if (real_create_object_URL) { return real_create_object_URL.call(real_URL, blob); } }; URL.revokeObjectURL = function(object_URL) { if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { real_revoke_object_URL.call(real_URL, object_URL); } }; FBB_proto.append = function(data/*, endings*/) { var bb = this.data; // decode data to a binary string if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { var str = "" , buf = new Uint8Array(data) , i = 0 , buf_len = buf.length ; for (; i < buf_len; i++) { str += String.fromCharCode(buf[i]); } bb.push(str); } else if (get_class(data) === "Blob" || get_class(data) === "File") { if (FileReaderSync) { var fr = new FileReaderSync; bb.push(fr.readAsBinaryString(data)); } else { // async FileReader won't work as BlobBuilder is sync throw new FileException("NOT_READABLE_ERR"); } } else if (data instanceof FakeBlob) { if (data.encoding === "base64" && atob) { bb.push(atob(data.data)); } else if (data.encoding === "URI") { bb.push(decodeURIComponent(data.data)); } else if (data.encoding === "raw") { bb.push(data.data); } } else { if (typeof data !== "string") { data += ""; // convert unsupported types to strings } // decode UTF-16 to binary string bb.push(unescape(encodeURIComponent(data))); } }; FBB_proto.getBlob = function(type) { if (!arguments.length) { type = null; } return new FakeBlob(this.data.join(""), type, "raw"); }; FBB_proto.toString = function() { return "[object BlobBuilder]"; }; FB_proto.slice = function(start, end, type) { var args = arguments.length; if (args < 3) { type = null; } return new FakeBlob( this.data.slice(start, args > 1 ? end : this.data.length) , type , this.encoding ); }; FB_proto.toString = function() { return "[object Blob]"; }; FB_proto.close = function() { this.size = this.data.length = 0; }; return FakeBlobBuilder; }(view)); view.Blob = function Blob(blobParts, options) { var type = options ? (options.type || "") : ""; var builder = new BlobBuilder(); if (blobParts) { for (var i = 0, len = blobParts.length; i < len; i++) { builder.append(blobParts[i]); } } return builder.getBlob(type); }; }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
總結(jié)
到此這篇關(guān)于vue導(dǎo)出報(bào)表至excel表格三種方式的文章就介紹到這了,更多相關(guān)vue導(dǎo)出報(bào)表excel內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Vue中this.$options.data()的this指向問題
這篇文章主要介紹了基于Vue中this.$options.data()的this指向問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Vue.sync修飾符與$emit(update:xxx)詳解
這篇文章主要介紹了Vue.sync修飾符與$emit(update:xxx),實(shí)現(xiàn)思路非常簡單,文章介紹了.sync修飾符的作用和使用.sync修飾符的寫法,實(shí)現(xiàn)代碼簡單易懂對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-11-11在Vue項(xiàng)目中引入騰訊驗(yàn)證碼服務(wù)的教程
這篇文章主要介紹了在Vue項(xiàng)目中引入騰訊驗(yàn)證碼服務(wù)的教程,需要的朋友可以參考下2018-04-04vue動(dòng)態(tài)繪制四分之三圓環(huán)圖效果
這篇文章主要介紹了vue動(dòng)態(tài)繪制四分之三圓環(huán)圖效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09vue實(shí)現(xiàn)橫屏滾動(dòng)公告效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)橫屏滾動(dòng)公告效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04使用vue3實(shí)現(xiàn)一個(gè)人喵交流小程序
Vue3 在經(jīng)過多個(gè)開發(fā)版本的迭代后,終于迎來了它的正式版本,下面這篇文章主要給大家介紹了關(guān)于如何使用vue3實(shí)現(xiàn)一個(gè)人喵交流小程序的相關(guān)資料,需要的朋友可以參考下2021-11-11Vue中Router路由兩種模式hash與history詳解
這篇文章主要介紹了Vue中Router路由的兩種模式,分別對(duì)hash模式與history模式作了簡要分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-09-09