用 vue-cli 快速構建項目 vue create ant-design-vue-pro
javascript
cd ant-design-vue-pro/
css
安裝必要依賴 npm i ant-design-vue moment
html
刪除/初始化 不須要的文件vue
// clear
└──src/
├───router/
│ └───index.js
├───views/
│ └───Home.vue
└───App.vue
複製代碼
引入 ant-design-vuejava
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.css";
複製代碼
debugger
node
import "ant-design-vue/dist/antd.less";
// 報錯
Syntax Error:
// https://github.com/ant-design/ant-motion/issues/44
.bezierEasingMixin();
// 解決方案:開啓 javascript
css: {
loaderOptions: {
less: {
loader: "less-loader",
options: {
javascriptEnabled: true,
},
},
},
},
複製代碼
import Button from "ant-design-vue/lib/button";
import "ant-design-vue/lib/button/style";
複製代碼
module.exports = {
presets: ["@vue/app"],
+ plugins: [
+ [
+ "import",
+ { libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
+ ]
+ ]
};
複製代碼
- import Button from 'ant-design-vue/lib/button';
+ import { Button } from 'ant-design-vue';
- import 'ant-design-vue/dist/antd.css'
複製代碼
bug
// ❌ 沒法全局引入
import Antd from 'antd-design-vue
複製代碼
現有方案linux
componentwebpack
const routes = [
{
path: "/user",
component: () =>
import(/* webpackChunkName: user */ "./component/RenderRouterView.vue"),
children: [
//...
],
},
];
複製代碼
const routes = [
{
path: "/user",
component: { render: (h) => h("router-view") },
children: [
//...
],
},
];
複製代碼
NProgressios
NProgress.start()
— shows the progress barNProgress.set(0.4)
— sets a percentageNProgress.inc()
— increments by a littleNProgress.done()
— completes the progress約定git
hideInMenu: true
name
字段才進行渲染hideChildrenMenu
,處理 「頁面在子路由時,菜單依然高亮」 的邏輯meta
,icon / title ...根據約定,生成動態菜單
const menuData = getMenuData(this.$router.options.routes);
getMenuData(routes){
}
複製代碼
利用函數式組件(無狀態,只接受參數) + 組件遞歸,渲染處理後的 routes 對象。
.sync
修飾符
this.$emit('update:title', newTitle)
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
複製代碼
<text-document v-bind:title.sync="doc.title"></text-document>
複製代碼
權限驗證相關函數
export async function getCurrentAuthority() {
const { role } = await this.$axios.$get("/user");
return ["admin"];
}
// some() 方法測試數組中是否是至少有1個元素經過了被提供的函數測試。它返回的是一個Boolean類型的值。
export function check(authority) {
const current = getCurrentAuthority();
return current.some((item) => authority.includes(item));
}
export function isLogin() {
const current = getCurrentAuthority();
return current && current[0] !== "guest";
}
複製代碼
路由守衛
import findLast from "lodash/findLast";
import { check, isLogin } from "utils/auth";
router.beforeEach((to, from, next) => {
// ...
const record = findLast(to.matched, (item) => item.meta.authority);
if (record && !check(record.meta.authority)) {
if (!isLogin() && to.path !== "/user/login") {
next({ path: "/user/login" });
} else if (to.path !== "/403") {
next({ path: "/403" });
}
// loading = false
// ...
}
// ...
});
複製代碼
側邊欄鑑權
routes.forEach((item) => {
if (item.meta && item.meta.authority && !check(item.meta.authority)) {
return;
}
});
複製代碼
403 添加彈窗提醒
import { notifiction } from "ant-deisgn-vue";
if (to.path !== "/403") {
notifiction.error({
message: "403",
description: "您沒有權限訪問該頁面,請聯繫管理員",
});
next({ path: "/403" });
}
複製代碼
權限組件 - 函數式組件
export default {
functional: true,
render: function (h, context) {
const { props, scopeSlots } = context;
return check(props.authority) ? scopeSlots.default() : null;
},
};
複製代碼
權限指令 - 插件式
export function install(Vue, options = {}) {
const { name = "auth" } = options;
Vue.directive(name, {
// 當被綁定的元素插入到 DOM 中時……
inserted: function (el, binding) {
if (!check(binding.value)) {
el.parentNode && el.parentNode.removeChild(el);
}
},
});
}
複製代碼
比較
echart 渲染寬度超出容器?
import { addListener, removeListener } from 'resize-detector'
resize 時,添加防抖
wait
毫秒後調用 func
方法。cancel
方法取消延遲的函數調用以及 flush 方法當即調用options.leading
與|或 options.trailing
決定延遲先後如何觸發(注:是 先調用後等待 仍是 先等待後調用)。created(){
this.resize = debounce(this.resize, 300)
}
複製代碼
監聽 option 變化
export default {
watch: {
option: {
handler: () => {},
deep: true,
},
},
};
複製代碼
option = {...option}
require.cache
: 被引入的模塊將被緩存在這個對象中。require.resolve
:在 node 中,能夠使用 require.resolve 來查詢某個模塊的完整路徑delete require.cache[require.resolve(name)]
module.exports = {
devServer: {
proxy: {
"/api": {
target: "http://localhost:8081",
bypass: function (req, res) {
if (req.headers.accept.indexOf("html") !== -1) {
console.log("Skipping proxy for browser request.");
return "/index.html";
} else {
// 根據約定尋找文件
const name = req.path.split("/api/")[1].split("/").join("_");
const mock = require(`./mock/${name}`);
const result = mock(req.method);
// 清理模塊緩存
require.cache(require.resolve(`./mock/${name}`));
return res.send(result);
}
},
},
},
},
};
複製代碼
添加環境變量 MOCK
運行跨平臺設置和使用環境變量(Node 中的環境變量)的腳本。
咱們在自定義配置環境變量的時候,因爲在不一樣的環境下,配置方式也是不一樣的。例如在 window 和 linux 下配置環境變量。
package.json
{
"scripts": {
"serve:no-mock": "cross-env MOCK=NONE "
}
}
複製代碼
const app = new (require("koa"))();
const mount = require("koa-mount");
app.use(
mount("/api/dashboard/chart", async (ctx) => {
ctx.body = [10, 20, 30, 40, 50];
})
);
app.listen(8081);
複製代碼
複製代碼
axios 攔截:二次封裝,統一錯誤處理
import axios from "axios";
function request(options) {
return axios(options)
.then((res) => {
return res;
})
.catch((error) => {
const {
response: { status, statusText },
} = error;
notifiction.error({
message: status,
describtion: statusText,
});
return Promise.reject(error);
});
}
複製代碼
Vue.prototype.$request = request
@vue/babel-preset-jsx
const state = () => ({ step: { payAccount: "" } });
const mutation = {
saveStepFormData(state, payload) {
state.step = { ...state.step, ...payload };
},
};
const actions = {
async submitStepForm({ commit }, payload) {
await request({ method: "POST", url: "", data: payload });
// 不該該是清空表單嗎?
commit("saveStepFormData", payload);
router.push("");
},
};
export default {
namespaced: true,
state,
mutations,
actions,
};
複製代碼
import { Icon } from "ant-design-vue";
const IconFont = Icon.createFromIconfontCN({ scriptUrl: "" });
複製代碼
<icon-font type="icon-404" />
複製代碼
<image url>
vue inspect > output.js
全局:config 配置
module.exports = {
css: {
loaderOption: {
less: {
modifyVars: {
"primary-color": "#1DA57A",
"link-color": "#1DA57A",
"border-radius-base": "2px",
},
},
},
},
};
複製代碼
局部:深度做用選擇器
若是你但願 scoped 樣式中的一個選擇器可以做用得「更深」,例如影響子組件,你能夠使用 >>> 操做符:
<style scoped>
.a >>> .b { /* ... */ }
</style>
複製代碼
在線動態編譯主題色
antd-vue 組件庫國際化:localProvider -> configProvider
<template>
<div id="app">
<a-config-provider :locale="locale"> </a-config-provider>
</div>
</template>
複製代碼
import zhCN from "ant-design-vue/lib/locale-provider/zh_CN";
import enUS from "ant-design-vue/lib/locale-provider/en_US";
export default = {
data(){
return {
locale: enUS
}
},
watch:{
"$route.query.locale"(val){
this.locale = val === 'enUS'? enUS : zhCN
}
}
}
複製代碼
moment 國際化
import moment from 'moment';
export default={
watch:{
"$route.query.locale"(val){
moment.locale(val==='enUS'?'en':'zh_cn');
}
}}
複製代碼
業務代碼國際化:VueI18n
main.js
import VueI18n from "vue-i18n";
import zhCN from "./locale/zhCN";
import enUS from "./locale/enUS";
import queryString from "query-string";
const i18n = new VueI18n({
locale: queryString.parse(location.search).locale || "zhCN",
message: {
zhCN: {
message: zhCN,
},
enUS: {
message: enUS,
},
},
});
new Vue({
router,
store,
i18n,
render: (h) => h(App),
}).$mount("#app");
複製代碼
zhCN.js / enUS.js
export default {
"app.workspace.title": "時間",
};
複製代碼
export default {
"app.workspace.title": "TIME",
};
複製代碼
workspace.vue
<template> {{$t('message')['app.workspace.title']}} </template>
複製代碼
handleLocale
export default {
watch: {
"$route.query.locale"(val) {
this.$i18n.locale = val;
},
},
};
複製代碼
打包分析報告:( VUE CLI )
npm run build -- --report
UI 組件按需加載 / babel
router 中使用 webpackChunkName
,對路由進行懶加載和拆包。
按需引入 lodash
import debounce from 'lodash/debounce'
複製代碼
使用插件 lodash-webpack-plugin
npm i lodash-webpack-plugin babel-plugin-lodash -D
複製代碼
babel.config.js
module.exports = {
presets: ["@vue/cli-plugin-babel/preset", "@vue/babel-preset-jsx"],
plugins: ["lodash"],
};
複製代碼
vue.config.js
const LodashModuleReplacementPlugin = require("lodash-webpack-plugin");
module.exports = {
chainWebpack: (config) => {
config
.plugin("loadshReplace")
.use(new LodashModuleReplacementPlugin());
},
};
複製代碼
lodash-es 結合 tree-shaking
import { debounce } from 'lodash-es'
複製代碼
tree-shaking 的做用,即移除上下文中未引用的代碼(dead code)
只有當函數給定輸入後,產生相應的輸出,且不修改任何外部的東西,才能夠安全作 shaking 的操做
如何使用tree-shaking?
確保代碼是 es6 格式,即 export,import
package.json 中,設置 sideEffects
確保 tree-shaking 的函數沒有反作用
babelrc 中設置presets [["env", { "modules": false }]]
禁止轉換模塊,交由 webpack 進行模塊化處理
結合 uglifyjs-webpack-plugin
import hljs from "highlight.js";
import "highlight.js/styles/github.css";
Vue.use(hljs.vuePlugin);
複製代碼
view.vue <highlightjs language="javascript" :code="ChartCode" />
複製代碼
auth.spec.js
import { authCurrent, check } from "@/utils/auth.js";
describe("auth test", () => {
it("empty auth", () => {
authCurrent.splice(0, authCurrent.length);
expect(check(["user"])).toBe(false);
expect(check(["admin"])).toBe(false);
});
});
複製代碼
jest.config.js
module.exports = {
preset: "@vue/cli-plugin-unit-jest",
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
},
resolver: null,
collectCoverage: process.env.COVERAGE === "true",
collectCoverageFrom: ["src/**/*.{js,vue}", "!**/node_modules/**"],
};
複製代碼
npm login
,登陸本身的 npm 帳號;npm publish
,·發佈本身的包到 npm;npm install
你發佈的包名,下載成功。注意
- 發佈本身包以前,應先去 npm 官網搜索本身要發佈的包名是否已經存在,已存在的包名會提交失敗;
- 本身發佈的包更新時,每次都要到 package.json, 將 version 修改,例如:從 1.0.0 改成 1.0.1。而後再執行 npm publish 更新;