作為前端的初學(xué)者凉逛,學(xué)一個(gè)前端框架是必不可少的纲爸。因?yàn)閷?duì)于新手而言覆醇,VUE相較于REACT更容易上手褥琐,所以作者選擇
了VUE锌俱。如果你正好也想學(xué)一個(gè)框架,那你走運(yùn)了哦敌呈。跟著作者一起來發(fā)開發(fā)一個(gè)簡單的電商項(xiàng)目贸宏,來學(xué)習(xí)VUE吧!
這是一個(gè)基于 vue & axios & mock & token & stylus & Cube-UI的電商項(xiàng)目demo磕洪,面向 vue 初學(xué)者吭练,場景雖簡單,但五臟俱全析显。涵蓋非常多的vue及其相關(guān)技術(shù)的基本操作鲫咽。有詳細(xì)的注釋,幫助大家快速上手 vue 谷异。且我整理了一些在vue開發(fā)過程中分尸,有可能會(huì)用到的技術(shù)文章,希望大家能在這些前輩們身上有所收獲歹嘹。
當(dāng)然如果您覺得這篇文章or這個(gè)項(xiàng)目對(duì)您的學(xué)習(xí)有所幫助箩绍,請(qǐng)不吝點(diǎn)個(gè)star鼓勵(lì)一下,當(dāng)然如果存在問題尺上,也非常希望您能跟我留言材蛛,一起學(xué)習(xí),共同進(jìn)步怎抛。
Github地址
- vue-jingdong (不要吝惜你的小星星哦)
- 話不多說上效果圖
項(xiàng)目技術(shù)棧
- 前臺(tái):vue & vue-router & vuex & vue-cli(webpack) & Cube-UI
- 后臺(tái):mock(用mock寫模擬api)
- 前后臺(tái)交互:axios
- 單點(diǎn)登錄:token
學(xué)習(xí)VUE項(xiàng)目開發(fā)推薦閱讀
此處有引用大佬贏弱小金魚的博客文章
- vue-cli 生成項(xiàng)目主體框架
- vue 全家桶
- axios前后臺(tái)交互
vue 和 node 的交互還是主要采用 ajax 來進(jìn)行仰税,此處就介紹一個(gè)主流交互工具 axios,當(dāng)然別的工具例如 vue-resource抽诉、jquery 都可以陨簇。但是 vue-resource 不維護(hù)了,jquery如果只是為了 ajax 就引入又太龐大,所以我個(gè)人是比較推薦axios
- axios全攻略-大佬小金魚寫的 - token
- 模擬后端mock
Mock.js 是一款模擬數(shù)據(jù)生成器河绽,旨在幫助前端攻城師獨(dú)立于后端進(jìn)行開發(fā)己单,幫助編寫單元測試。提供了以下模擬功能:根據(jù)數(shù)據(jù)模板生成模擬數(shù)據(jù)耙饰,模擬 Ajax 請(qǐng)求纹笼,生成并返回模擬數(shù)據(jù),基于 HTML 模板生成模擬數(shù)據(jù)
- 來自滴滴的CUBE-UI
隨著 vue 的不斷發(fā)展苟跪,社區(qū)越來越活躍廷痘,因此產(chǎn)生了許多組件庫。由于滴滴的這個(gè)組件沒有停止更新和維護(hù)件已,特別適合開發(fā)上線項(xiàng)目笋额,所以我們這里選擇Cube-UI。
- Cube-UI文檔
正文部分
學(xué)了那么多文章篷扩,一定進(jìn)步不少吧兄猩。讓我們來進(jìn)行實(shí)戰(zhàn)開發(fā),進(jìn)行應(yīng)用鉴未。一起來吧枢冤,先苦后甜!
項(xiàng)目結(jié)構(gòu)
引入Cube-UI并使用
npm install cube-ui --save
安裝后會(huì)自動(dòng)出現(xiàn)cube-ui.js
import Vue from 'vue'
import Cube from 'cube-ui'
Vue.use(Cube)
下面我們來使用它
我們來寫注冊頁面
<template>
<div>
<img class="headerimg" src="https://www.baidu.com/img/bd_logo1.png" alt="">
<cube-form
:model="model"
:schema="schema"
@submit="submitHandler"
></cube-form>
</div>
</template>
<script>
export default {
data(){
return{
model:{//數(shù)據(jù)源
username:'',
password:''
},
schema:{//生成表單依賴的模式
fields:[//子配置項(xiàng) 模式用于定義表單中的各個(gè)字段铜秆,可以選擇是否分組淹真。 無分組
//用戶名配置
{
type:'input',//字段類型
modelKey:'username',//在表單的 model 數(shù)據(jù)源對(duì)象中所對(duì)應(yīng)的 key 名字
label:'用戶名',//字段的標(biāo)簽值
props:{
placeholder: '請(qǐng)輸入用戶名',
},
rules:{
//校驗(yàn)規(guī)則
required: true,
type: 'string',
min: 3,
max: 15,
},
trigger: 'blur',//如果設(shè)置為 'blur' 那么則會(huì)在離焦后校驗(yàn)
messages:{
required: '用戶名不能為空',
min: '用戶名不能少于三個(gè)字符',
max: '用戶名不能超過十五個(gè)字符',
}
},
//密碼配置
{
type:'input',//字段類型
modelKey:'password',//在表單的 model 數(shù)據(jù)源對(duì)象中所對(duì)應(yīng)的 key 名字
label:'密碼',//字段的標(biāo)簽值
props:{
placeholder: '請(qǐng)輸入密碼',
type:'password',
eye:{
open: false,
}
},
rules:{
required:true,
},
trigger: 'blur',
},
{
type:'submit',
label: '注冊'
}
]
}
}
},
這個(gè)是注冊頁面的UI代碼,我們引用組件中的cube-form表單连茧,對(duì)它輸入的值進(jìn)行規(guī)則限定與驗(yàn)證趟咆,如果還不懂可以看看前面作者發(fā)的cube-ui文檔哦,里面有詳細(xì)介紹梅屉,也可以去GitHub下載demo值纱,自己操作試試。 登陸頁面也類似坯汤,我就不贅述啦~
用mock寫模擬api
作為一個(gè)前端開發(fā)人員虐唠,在后端沒有提供接口的情況下,自己編寫模擬接口惰聂,對(duì)項(xiàng)目功能進(jìn)行測試是十分重要的一項(xiàng)技能疆偿。擁有這項(xiàng)技能,將不會(huì)影響整個(gè)項(xiàng)目的開發(fā)進(jìn)度搓幌。下面我們一起來編寫杆故。
我在vue.config.js對(duì)vue的配置文件中寫啦,注冊與登陸的接口溉愁,并編寫了模擬數(shù)據(jù)处铛,代碼如下:
module.exports = {
configureWebpack: {
devServer: {
port: 8080, //端口號(hào)
open: true, //自動(dòng)打開瀏覽器
//mock 接口編寫的地方 //假數(shù)據(jù) //每次做更改配置文件時(shí),都必須重啟項(xiàng)目才會(huì)生效
before(app) {
// app.get('請(qǐng)求地址',(req,res) =>{
// res.json({
// xinxi
// })
// })
//注冊接口
//用戶信息池
let userpoor = [{
username: 'xxyang',
password: '123456'
},
{
username: 'liuqiangdong',
password: '888888'
}
]
//注冊接口
app.get('/api/register', (req, res) => {
const {
username,
password
} = req.query
const userlength = userpoor.filter(v => v.username == username).length //過濾 查找是否存在用戶名
if (userlength > 0) {
res.json({
success: false,
message: '用戶名已存在'
})
} else {
res.json({
success: true,
message: '注冊成功'
})
}
})
//登陸接口
let tokenkey = 'xdclass'
app.get('/api/login', (req, res) => {
const {
username,
password
} = req.query
if (username == 'xxyang' && password == '123456' || username == 'liudongqiang' && password == '123456') {
res.json({
code: 0,
message: '登陸成功',
token: tokenkey + '-' + username + '-' + (new Date().getTime() + 60 * 60 * 1000) //token過期時(shí)間1個(gè)小時(shí)
})
} else {
res.json({
code: 1,
message: '賬號(hào)或密碼錯(cuò)誤'
})
}
})
}
}
},
css: {
loaderOptions: {
stylus: {
'resolve url': true,
'import': [
'./src/theme'
]
}
}
},
pluginOptions: {
'cube-ui': {
postCompile: true,
theme: true
}
}
}
以上代碼中作者有詳細(xì)注釋,煩請(qǐng)不懂的話自行看一下撤蟆。我解釋下這一句代碼:
const userlength = userpoor.filter(v => v.username == username).length //過濾 查找是否存在用戶名
用filter過濾方法將輸入的用戶賬號(hào)和已有的賬號(hào)進(jìn)行對(duì)比奕塑,如果相同則會(huì)返回true。這時(shí)就會(huì)獲得userpoor的這條用戶賬號(hào)家肯,此時(shí)長度大于零龄砰,所以輸出false,提示用戶已存在。
用token加密并儲(chǔ)存密碼
不知各位小伙伴知不知道讨衣,每年都要大量用戶的信息泄露换棚,例如CSDN以前被黑客攻擊泄露了,幾百萬條用戶信息反镇,而且用戶密碼是明文的固蚤。這個(gè)時(shí)間爆發(fā),讓CSDN受到了愿险,很大的影響颇蜡〖鬯担可想而知辆亏,對(duì)密碼進(jìn)行加密是十分重要的。token可以對(duì)密碼進(jìn)行加密鳖目,下面請(qǐng)看這個(gè)demo密碼加密后的圖片:
如圖所示對(duì)密碼進(jìn)行了加密扮叨,而且加了頭部xdclass進(jìn)一步簡單加密。而且我們儲(chǔ)存在本地瀏覽器中了领迈,避免在短時(shí)間內(nèi)要多次登陸彻磁。下面我們來看代碼吧。
登陸接口
//登陸接口
let tokenkey = 'xdclass'
app.get('/api/login', (req, res) => {
const {
username,
password
} = req.query
if (username == 'xxyang' && password == '123456' || username == 'liudongqiang' && password == '123456') {
res.json({
code: 0,
message: '登陸成功',
token: tokenkey + '-' + username + '-' + (new Date().getTime() + 60 * 60 * 1000) //token過期時(shí)間1個(gè)小時(shí)
})
} else {
res.json({
code: 1,
message: '賬號(hào)或密碼錯(cuò)誤'
})
}
})
這里我們對(duì)token進(jìn)行了頭部加密狸捅,和設(shè)置了token的有效時(shí)間為一個(gè)小時(shí)衷蜓,一個(gè)小時(shí)內(nèi),用戶不用重新登陸尘喝。
用VUEX將token儲(chǔ)存在本地
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: ''
},
mutations: {
//設(shè)置vuex的token
settoken(state,token){
state.token=token
}
},
actions: {
},
modules: {
},
getters:{
}
})
調(diào)用API返回并儲(chǔ)存token
methods: {
async submitHandler(e) {
e.preventDefault()
try{
const result = await this.$http.get('/api/login',{params:this.model})
// console.log(result.data.token)
if(result.code == '0'){
// alert(result.data.message)
this.$store.commit('settoken', result.token)
window.localStorage.setItem('token', result.token)
this.$router.replace({path:'/botnav/index'})
}else{
alert(result.message)
}
}catch(err){
console.log(err)
}
},
判斷賬號(hào)密碼是否正確磁浇,如果正確本地保存token,并且跳轉(zhuǎn)路由到首頁朽褪。
用axios進(jìn)行攔截
前面有提到axios是用來進(jìn)行前后臺(tái)交互的置吓,起一個(gè)中間件的作用,為服務(wù)器端處理了一些事情缔赠,可以減輕服務(wù)器的壓力衍锚。我們之前有給token設(shè)置了一個(gè)有效時(shí)間,過期了怎么辦嗤堰,改進(jìn)行什么操作呢戴质,這時(shí)候我們的axios出現(xiàn)啦!
我們用axios去對(duì)http進(jìn)行全局?jǐn)r截,并把token放在頭部置森,每次請(qǐng)求有返回的都是先經(jīng)過攔截器的斗埂。如果登陸過期,需要重新登陸并清空vuex和localstorage 的token凫海,而且會(huì)跳轉(zhuǎn)到login頁面呛凶。話不多說,我們上代碼:
import axios from 'axios'
import store from './store'
import router from './router'
//http 全局?jǐn)r截
//token 要放在我們請(qǐng)求的header上面帶回去給反饋
export default function sexAxios() {
axios.interceptors.request.use(
config => {
if(store.state.token){
config.headers.token = store.state.token
}
return config
}
)
//每次請(qǐng)求有返回的都是先經(jīng)過攔截器的
axios.interceptors.response.use(
response => {
if(response.status == 200){
const data = response.data
if(data.code == -1){
//登陸過期 需要重新登陸 清空vuex和localstorage 的token
store.commit('settoken','')
localStorage.removeItem('token')
//跳轉(zhuǎn)到login頁面
router.replace({path:'/login'})
}
return data
}
return response
}
)
}
這里作者就不做過多解釋行贪,業(yè)務(wù)邏輯理清楚啦漾稀,有問題的小伙伴可以給我留言或者私信。
寫在后面
引用小金魚的一句話建瘫,當(dāng)然紙上學(xué)來終覺淺崭捍,絕知此事要躬行。學(xué)完理論就需要去實(shí)踐啰脚,大家看完之后一定要自己去操作一下殷蛇,不然似懂非懂,第二天就忘啦橄浓。在此作者再次附上GitHub的地址vue-jingdong (不要吝惜你的小星星哦)粒梦。這是一個(gè)系列文章,未完待續(xù)荸实,期待與你一起學(xué)習(xí)匀们。如果對(duì)你有幫助的話,不妨送上你的star准给,送人玫瑰泄朴,手留余香,謝謝露氮!