摘要:輸入框內(nèi)容過濾產(chǎn)品有一個(gè)需求是,在搜索用戶信息時(shí),只能通過郵箱搜索,并且只能輸入字母數(shù)字以及。我選擇了輸入框的值這里的坑就是需要在中更新值,因?yàn)樵剡@時(shí)才刷新。是否有一定要用的必要類似的管理系統(tǒng)涉及到不同頁(yè)面之間的交互都很少。
初始化項(xiàng)目
使用 Vue-cli3 初始化項(xiàng)目1
安裝 Element UI
安裝 Vue-i18n,做相關(guān)配置2,3
原則上需要對(duì) Element 也做 I18n 的處理,但是我覺得 Element 中已經(jīng)有很完善的多語(yǔ)言翻譯,而 Element 自身尚不支持 Vue-i18n 7+ 版本,要特殊處理,所以就算了,這里直接使用了 Element 自帶的方法。項(xiàng)目結(jié)構(gòu)
. |-- babel.config.js |-- package.json |-- public | `-- index.html |-- src | |-- App.vue | |-- assets | | |-- override-element-ui.less // 覆蓋 Element 默認(rèn)樣式 | | `-- image // 圖片文件目錄 | |-- components // 所有非 `Element 按需加載` 中顯示的頁(yè)面的 Vue 組件 | | |-- mainMenu.vue // 左側(cè)導(dǎo)航 | | |-- pureTitle.vue // 通用的 Title 組件,項(xiàng)目中有多個(gè)頁(yè)面會(huì)用到 | | |-- search.vue // 通用的 Search 頭部組件,同樣會(huì)用到 | | `-- userCenter.vue // 字面意思用戶中心,目前只需要顯示用戶名,handle 用戶退出操作??深A(yù)見:下拉菜單操作、頭像顯示等... | |-- main.js // Vue-cli 生成的項(xiàng)目基本文件 | |-- router.js // Vue-cli 生成,路由 | |-- store // Vuex相關(guān) | | |-- index.js | | |-- mutationTypes.js | | `-- module // 這里按照路由劃分了 module,不一定對(duì) | | | |-- someModule.js | | | `-- elseModule.js | |-- utils | | |-- i18n // 國(guó)際化支持 | | | |-- index.js | | | `-- lang // 語(yǔ)言字符串文件 | | | |-- en.json | | | `-- zh.json | | |-- request // 處理所有 ajax 請(qǐng)求 | | | |-- index.js // 基于 axios,封裝了需要用到的方法,例如 token 的處理 | | | |-- someComponentName.js // 基于組件分割的請(qǐng)求,在 Vuex action 中調(diào)用獨(dú)立方法 | | | `-- elseComponentName.js | | |-- timeHelper.js // 時(shí)間戳轉(zhuǎn)換幫助函數(shù) | | `-- userHelper.js // 保存用戶信息幫助函數(shù) | `-- views // ` 下內(nèi)容顯示組件` | |-- Home.vue | |-- Login.vue | |-- MainPage.vue | |-- Manage.vue | `-- Verify.vue |-- .env.development // 環(huán)境變量 process.env |-- .env.production // 生產(chǎn)環(huán)境下的環(huán)境變量 `-- vue.config.js // 更改 Vue-cli 默認(rèn)配置
先看一張項(xiàng)目初始狀態(tài)下,全局引入 Element & 按需引入打包大小的對(duì)比:
How參考:按需引入
需要注意的地方是:
不用新建 .babelrc 文件,只需要更改 babel.config.js
使用 Vue-cli 初始化項(xiàng)目后, presets 中為 ["@vue/app"],不需要更改為 element 官網(wǎng)中的 es2015 。原因是 babel 的目前版本已經(jīng)不推薦按照 JavaScript 版本來區(qū)分編譯目標(biāo)。(// todo:添加相關(guān)鏈接)
可用的 babel.config.js 文件如下:
module.exports = { presets: [ ["@vue/app"], ], plugins: [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }覆蓋默認(rèn)樣式
正常情況下,可以通過直接修改對(duì)應(yīng) class 的內(nèi)容修改。但含有 foo__bar 類似格式的樣式不會(huì)應(yīng)用 scoped(因?yàn)椴皇峭粋€(gè) Vue 實(shí)例),因此修改不會(huì)生效。
可以通過在 *.vue 中不使用 scope 來解決這個(gè)問題,Element 在 Issue 中也吐槽過。雖然我不認(rèn)為 scope 不是一個(gè)好的解決方案。
因此,我選擇了在 main.js 中引入外部樣式表,例如override-element-ui.less,在外部樣式表中修改 foo__bar 類名的樣式。
路由設(shè)計(jì)route.js 主要設(shè)計(jì)如下:
routes: [ { path: "/login", name: "login", component: Login }, { path: "/", name: "home", component: Home, children: [ { path: "/index", component: mainPage }, { path: "/manage", component: manage, children: [ { path: "user/:uumsid&:userid", component: userDetail }, { path: "enterprise/:id", component: insDetail }, { path: "/", component: manageList }, ] }, { path: "/verify", component: Verify, }, { path: "/verify/:id", component: VerifyDetail }, { path: "*", redirect: "/index" }, ] }, ]
555...不太想貼代碼,感覺太亂、太長(zhǎng)。
但不貼又說不清楚。
簡(jiǎn)單來說,項(xiàng)目只分為兩個(gè)部分。登陸頁(yè)和功能頁(yè)。
根路由綁定到了登陸后的首頁(yè)。
首頁(yè)包含頭部標(biāo)題、左側(cè)菜單還有顯示內(nèi)容的
因此,如果用戶僅輸入 location.host 訪問網(wǎng)站,會(huì)被帶到 ${host}/index 頁(yè)面。另外,訪問任意未被匹配的 path,都會(huì)重定向到 index 頁(yè)面。
這個(gè)時(shí)候會(huì)出現(xiàn)兩個(gè)分支:
判斷本地是否存在用戶信息是否存在 ? 進(jìn)行正常操作 :重定向到登錄頁(yè)
如何保存用戶信息和登陸狀態(tài)整個(gè)系統(tǒng)只需要分成需要登錄和不需登陸兩個(gè)部分。
當(dāng)前所開發(fā)的系統(tǒng)除登錄頁(yè)外,都需要登錄后訪問。
這個(gè)部分和路由設(shè)計(jì)強(qiáng)相關(guān)。何時(shí)判斷用戶是否登錄在上一部分已經(jīng)解釋過。
使用 localstorage 來持久化保存用戶信息,處理用戶刷新頁(yè)面以及一段時(shí)間內(nèi)關(guān)閉瀏覽器后不用重新登錄的需求。(一段時(shí)間為30min)
在 Home.vue 的 created() 鉤子中做如下操作:
created() { let userInfo = getUserFromLocal("userinfo") let verifiedUserInfo = (info) => { let now = new Date().getTime() const PASS_TIME = 1000 * 60 * 30 // 30min if (!info) return false if (now - info.time < PASS_TIME) return true return false } if (!!verifiedUserInfo(userInfo)) { this.onRefresh(userInfo) } else { this.$router.push({path: "/login"}) } }
其中,getUserFromLocal 是在 userHelper.js 中寫的從 localstorage 中獲取數(shù)據(jù)的方法。通過判斷用戶信息是否存在以及是否過期來決定是跳轉(zhuǎn)到登錄頁(yè)還是直接使用當(dāng)前已有的用戶信息。
// 我不覺得這是一個(gè)很完美的方案,但根據(jù)我搜索的資料來看,確實(shí)沒有詳細(xì)說過這方面內(nèi)容的文章。所以,期待能看到更好的方案。
如何優(yōu)雅的觸發(fā)表單驗(yàn)證Element 的表單驗(yàn)證方法
但沒有給出 async-validator 支持的表單驗(yàn)證觸發(fā)方式。
經(jīng)過查找,支持的觸發(fā)方式有: submit, blur, input
我選擇的方案是在規(guī)則中使用 submit 時(shí)驗(yàn)證(指表單提交時(shí)觸發(fā),因此實(shí)際情況中永遠(yuǎn)不會(huì)觸發(fā),但能滿足需求,即手動(dòng)觸發(fā)驗(yàn)證。)
同時(shí),在點(diǎn)擊登錄或者發(fā)送請(qǐng)求按鈕時(shí),調(diào)用 this.$refs.[formEl].validate((boolean) => { // callback})
清除表單驗(yàn)證結(jié)果:
當(dāng)表單項(xiàng)很多時(shí),也可以在中調(diào)用clearValidate(prop), prop 指表單項(xiàng)的 name 值。
輸入框內(nèi)容過濾產(chǎn)品有一個(gè)需求是,在搜索用戶信息時(shí),只能通過郵箱搜索,并且只能輸入字母、數(shù)字以及@。因此,我們需要對(duì)用戶輸入數(shù)據(jù)時(shí)即時(shí)進(jìn)行過濾。(別問我為什么不在用戶輸入完成后提示錯(cuò)誤,這是需求。
我選擇了 watch 輸入框 value 的值:
value(val) { this.$nextTick(() => { this.value = this.reg ? val.replace(this.reg, "") : val }) }
這里的坑就是需要在 $nextTick() 中更新 value 值,因?yàn)?DOM 元素這時(shí)才刷新。
這個(gè)需求有許多 blog 都給出過不同的解決方案,可以多看看選擇一下。
獲取數(shù)據(jù)時(shí)的細(xì)節(jié)問題 ajax 的封裝基于 axios
./utils/request/index.js:
import axios from "axios" // BASE_HOST 通過 .env.[development|production] 配置。注意:每個(gè)變量都要用 VUE_APP作為前綴,否則不能識(shí)別 const BASE_HOST = process.env.VUE_APP_API_BASE const TIME_OUT = 1000 * 10 /** * * @param URL {string} * @param params {Object} */ export function POST(URL, params) { if (!URL.includes(BASE_HOST)) URL = BASE_HOST + URL return axios({ method: "post", url: URL, data: params, timeout: TIME_OUT }) } export function GET(URL, data) { // like POST } /** * @param URL {string} * @param token {string} * @param params {Object} */ export function GET_WITH_TOKEN(URL, token, params) { if (!URL.includes(BASE_HOST)) URL = BASE_HOST + URL return GET(URL, { params, headers: { token: token }, timeout: TIME_OUT }) }
封裝了基本的 GET,POST等方法,沒想到什么特別的作用,也沒有想到不好的地方,留著為了以防萬(wàn)一。(事實(shí)上,也用上了。比如超時(shí)處理。但是,超時(shí)處理在下一層也能做。但這樣的話登陸就需要多帶帶設(shè)置超時(shí)了。)
GET_WITH_TOKEN(以及 POST_WITH_TOKEN 等) 用于需要登錄鑒權(quán)的接口
顯示 Loading 狀態(tài)在等待api返回?cái)?shù)據(jù)時(shí)可以用loading告訴用戶頁(yè)面正在加載。Element 提供的 Loading組件
一般切換路由后,會(huì)在組件的 created() 方法中發(fā)送請(qǐng)求。這種情況下應(yīng)該在 nextTick()(或者mounted()中) 中調(diào)用 loading ,避免頁(yè)面切換時(shí)找不到 DOM,出現(xiàn)全屏 loading 或頁(yè)面閃爍。
尚不明確(梗I18n 的方案不夠完善,現(xiàn)在做到了語(yǔ)言文件的熱切換,但是對(duì)業(yè)務(wù)來講似乎沒有什么必要。沒有做語(yǔ)言字符串的按需加載(事實(shí)上是做了但沒有實(shí)現(xiàn)),但這個(gè)似乎比熱切更重要一點(diǎn)。
按照 Vue-router 實(shí)現(xiàn)了懶加載及文件命名,但瀏覽器似乎仍然會(huì)下載所有 JS 文件,在 JS Tab 中可以看到只下載了當(dāng)前頁(yè)用到的文件。
Vuex 是否有一定要用的必要?類似的管理系統(tǒng)涉及到不同頁(yè)面之間的交互都很少。在該系統(tǒng)中完全沒有,雖然有不同組件的交互,但都能較簡(jiǎn)單的把狀態(tài)提升到其父組件。因此,Vuex 唯一必須要用的理由就是保存用戶狀態(tài)。因?yàn)榈顷懞蟮慕涌诙夹枰?token 校驗(yàn),保存在 Vuex 中可以非常方便的使用。
參考資料Vue CLI 3
Vue I18n
如何讓一個(gè)vue項(xiàng)目支持多語(yǔ)言(vue-i18n)
同步在博客:https://blog.life1st.me/artic...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/98131.html
摘要:利用中間件實(shí)現(xiàn)異步請(qǐng)求,實(shí)現(xiàn)兩個(gè)用戶角色實(shí)時(shí)通信。目前還未深入了解的一些概念。往后會(huì)寫更多的前后臺(tái)聯(lián)通的項(xiàng)目。刪除分組會(huì)連同組內(nèi)的所有圖片一起刪除。算是對(duì)自己上次用寫后臺(tái)的一個(gè)強(qiáng)化,項(xiàng)目文章在這里。后來一直沒動(dòng),前些日子才把后續(xù)的完善。 歡迎訪問我的個(gè)人網(wǎng)站:http://www.neroht.com/? 剛學(xué)vue和react時(shí),利用業(yè)余時(shí)間寫的關(guān)于這兩個(gè)框架的訓(xùn)練,都相對(duì)簡(jiǎn)單,有的...
摘要:用來主要前臺(tái)的請(qǐng)求,并處理返回相關(guān)的數(shù)據(jù),做后臺(tái)服務(wù)。總結(jié)做完這個(gè)項(xiàng)目,其中的過程還是挺艱辛的,畢竟都是邊學(xué)邊做,不過最后能完成還是挺開心的,終于有了一個(gè)從到的項(xiàng)目過程。雖然只是一個(gè)小小的練手項(xiàng)目,不過對(duì)于目前的我,感覺還是不錯(cuò)的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:用來主要前臺(tái)的請(qǐng)求,并處理返回相關(guān)的數(shù)據(jù),做后臺(tái)服務(wù)??偨Y(jié)做完這個(gè)項(xiàng)目,其中的過程還是挺艱辛的,畢竟都是邊學(xué)邊做,不過最后能完成還是挺開心的,終于有了一個(gè)從到的項(xiàng)目過程。雖然只是一個(gè)小小的練手項(xiàng)目,不過對(duì)于目前的我,感覺還是不錯(cuò)的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:用來主要前臺(tái)的請(qǐng)求,并處理返回相關(guān)的數(shù)據(jù),做后臺(tái)服務(wù)??偨Y(jié)做完這個(gè)項(xiàng)目,其中的過程還是挺艱辛的,畢竟都是邊學(xué)邊做,不過最后能完成還是挺開心的,終于有了一個(gè)從到的項(xiàng)目過程。雖然只是一個(gè)小小的練手項(xiàng)目,不過對(duì)于目前的我,感覺還是不錯(cuò)的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
閱讀 3586·2021-10-11 10:58
閱讀 2090·2021-09-24 09:47
閱讀 571·2019-08-30 14:19
閱讀 1852·2019-08-30 13:58
閱讀 1502·2019-08-29 15:26
閱讀 687·2019-08-26 13:45
閱讀 2204·2019-08-26 11:53
閱讀 1831·2019-08-26 11:30