謝謝你們指正,我以前分不清,vue3指的是vue3仍是vue-cli3,我這裏講的確實是vue-cli3,我這裏訂正下。以前router的代碼是貼錯了,也感謝網友的指正,已訂正。javascript
至於評論裏噴個人,本人聲明下吧,本文只合適誠心學習交流的人觀看,傻逼請略過。css
----分割線----html
如下是正文前端
提及來有點丟人,我已經使用vue很久了,可是怎麼從0開始配置一個vue項目,每次仍是要百度。此次決定寫個博客,增強下記憶,若是再記不住就直播本身的女友洗澡。vue
如下以新建一個圖書管理項目爲例。我使用vue3新建項目,對於建立一個項目來講,vue3真的比vue2簡單不少。java
建立vue項目,首先要確保全局安裝了vue命令行工具。node
我這邊使用yarn而不用npm,由於yarn要比npm好用的多,強烈推薦使用。若是你們對yarn不熟悉,我這邊免費贈送個人yarn教程。點擊查看。ios
yarn add global @vue/cli
複製代碼
使用vue-cli3開發項目,可使用圖形化界面,也可使用命令行,還能夠基於原型進行開發。我這裏以常見的基於命令行的開發爲例。git
我想在我D盤的test文件夾下新建一個圖書管理項目,項目名叫book。執行以下命令便可。github
D:\test>vue create book
複製代碼
這裏能夠選擇咱們須要安裝的預處理器preset。咱們能夠直接選下圖中的第一個選項,這樣能夠省去不少麻煩。不過這裏爲了講解須要,咱們選擇默認的(bable+eslint)。日後咱們再討論怎麼手動安裝其餘preset。我強烈建議你選擇第一項,這樣真的能夠省去不少麻煩。
程序執行完後,項目結構以下:
.
|-book
|-babel.config.js
|-package.json
|-public
| |-favicon.ico
| |-index.html
|-README.md
|-src
| |-App.vue
| |-assets
| | |-logo.png
| |-components
| | |-HelloWorld.vue
| |-main.js
|-yarn.lock
複製代碼
將命令行路徑設置爲book項目所在的路徑
D:\test>cd book
複製代碼
啓動項目
yarn serve
複製代碼
執行完,我這邊沒有報錯,就說明安裝沒有問題。
vue已經給咱們新建了一個初始的項目結構,可是這個項目結構還不完善。咱們須要新建一下幾個目錄。新建的目錄都是新建在src目錄下。
此時的目錄結構以下:
|-book
|-babel.config.js
|-package.json
|-public
| |-favicon.ico
| |-index.html
|-README.md
|-src
| |-api
| |-App.vue
| |-assets
| | |-logo.png
| |-components
| | |-HelloWorld.vue
| |-main.js
| |-router
| |-store
| | |-index.js
| |-utils
| |-views
|-yarn.lock
複製代碼
咱們要講解vue的使用,總的拿個項目練手。我就作一回產品經理,虛擬一個圖書管理項目吧。咱們有2個頁面。分別以下
這個項目會涉及到那些操做呢:
所以處理,vue提供給咱們的組件外,咱們還須要手動添加一下這些組件
好了如今咱們根據咱們的需求,一步步開發咱們的頁面。
<template>
<!-- 這是login頁面 -->
<div>這裏是login 頁面</div>
<!-- 這是index頁面 -->
<div>這裏是index 頁面</div>
</template>
<style> </style>
<script> export default { name: 'Login', data() { return { } }, } </script>
複製代碼
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<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>
複製代碼
使用vue開發任何一個項目都涉及都路由,因此咱們先講解路由。這裏須要安裝的組件是vue-router
D:\test\book>yarn add vue-router
複製代碼
在咱們剛剛新建的router文件夾下新建index.js文件,程序以下
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login.vue'
import Index from '../views/Index.vue'
import Detail from '../views/Detail.vue'
Vue.use(Router)
const router = new Router({
routes: [{
path: '/',
redirect: '/index'
}, {
path: '/login',
name: 'Login',
component: Login
}, {
path: '/index',
name: 'Index',
component: Index
}, {
path: '/detail',
name: 'Detail',
component: Detail
}]
})
export default router
複製代碼
修改main.js,引入咱們的路由。在第3行我引入了路由,在new Vue的時候還須要把router加進去了,這樣才能正常使用路由。
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
複製代碼
好了如今咱們能夠訪問咱們的頁面了,忽略連接上的端口號,vue會根據你電腦端口的使用狀況,自動選擇一個合適的端口號,因此個人端口號可能跟你的不一樣。
ok 自此咱們的路由配置成功。我這邊訪問頁面是沒有問題,若是你有問題,你就找下本身的錯誤在哪裏。
下面就進入咱們的頁面開發模式,首先咱們要開發的是login頁。咱們可使用原生的html開發,可是,效率低下,因此咱們仍是用vue組件吧。這裏我以element-ui爲例
安裝
D:\test\book>yarn add element-ui
複製代碼
配置:在main.js中引入element
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 引入element-ui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI)
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
複製代碼
修改Login.vue。
把代碼修改爲下面這樣子後,咱們的表單就建完了。打開頁面。發現咱們頁面功能是有了,可是太醜了,表單佔據了整個頁面的寬度,所以咱們還要修改下樣式。這裏咱們就要用到sass
<template>
<div class="login">
<div class="l-form">
<div class="l-tip">圖書館管理系統</div>
<el-form ref="form" :model="form">
<el-form-item>
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item>
<el-input v-model="form.password" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">登陸</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script> export default { name: 'Login', data() { return { form: { name: '', password: '' } } }, methods: { onSubmit() { }, }, } </script>
<style> </style>
複製代碼
咱們能夠直接用css的,可是我不推薦這樣用,由於原生太醜了。咱們要使用css預處理器寫css樣式。css預處理器有sass和less,固然還有其餘的可是我沒用過。less我不推薦使用,由於功能不強、像自定義函數功能就沒有,寫代碼特別彆扭,我推薦sass。
安裝sass
D:\test\book>yarn add node-sass sass-loader
複製代碼
vue-cli3 對sass簡直是0配置,上面咱們安裝好處理器後,直接在style標籤上加上lang="scss"
就可使用sass了。
修改Login.vue中的style
<style lang="scss"> .login { width: 100%; height: 100%; background: #000; .l-form { position: fixed; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%); width: 300px; margin: auto; border-radius: 8px; background: #fff; padding: 20px; .l-tip { text-align: center; font-size: 24px; font-weight: bold; } .el-form { width: 100%; margin: auto; margin-top: 20px; .el-form-item { button { width: 100%; } } } } } </style>
複製代碼
樣式跟咱們想要的還有點差異,這是是由於父元素的樣式問題引發的,修改App.vue中的style。主要是給html,body還有#app元素設置了寬和高和邊距。
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<style lang="scss"> html, body, #app{ width: 100%; height: 100%; margin: 0px; padding: 0px; } </style>
複製代碼
再打開瀏覽器,看咱們的頁面,已經很好看了。頁面長下面這樣。
安裝normalize.css 其實這個安不安裝均可以,我是有強迫症就安裝了。
安裝
yarn add normalize.css
複製代碼
修改main.js引入normalize.css。
配置
import 'normalize.css'
複製代碼
咱們在登陸頁要登陸,這就涉及到了發ajax請求,這個咱們使用axios
安裝
D:\test\book>yarn add axios
複製代碼
使用
在api文件夾下新建config.js文件,配置一些請求的通用選項,同時還對gei和post請求進一步封裝。其實封裝不封裝都無所謂,我我的感受封裝後會省事一點。代碼以下:
import axios from "axios"
import { Message } from "element-ui"
// 這個baseUrl要根據實際狀況進行改變
axios.defaults.baseURL = "/"
axios.defaults.headers.common["Content-Type"] =
"application/json; charset=UTF-8"
axios.defaults.headers.common["Access-Control-Allow-Origin"] = "*"
// 請求攔截器 添加token
axios.interceptors.request.use(
config => {
return config
},
error => {
return Promise.reject(error)
}
)
// 響應攔截器即異常處理
axios.interceptors.response.use(
response => {
return response
},
error => {
Message({
message: error.message,
type: "error",
duration: 5000,
})
return Promise.resolve(error)
}
)
export default {
// get請求
get(url, param) {
return new Promise((resolve, reject) => {
axios({
method: "get",
url,
params: param,
})
.then(res => {
resolve(res)
})
.catch(error => {
Message({
message: error,
type: "error",
duration: 5000,
})
reject(error)
})
})
},
// post請求
post(url, param) {
return new Promise((resolve, reject) => {
axios({
method: "post",
url,
data: param,
})
.then(res => {
resolve(res)
})
.catch(error => {
Message({
message: error,
type: "error",
duration: 5000,
})
reject(error)
})
})
},
// all get
allGet(fnArr) {
return axios.all(fnArr)
},
}
複製代碼
在api的文件夾下新建login.js文件。這個函數的做用就是請求後臺的login接口。
代碼以下:
import service from './config'
class Login {
login(params) {
return service.post('login', params)
}
}
export default new Login()
複製代碼
axios不用特別配置的,引入就能夠用。如今問題來了,有了接口了,可是咱們沒有後臺啊。咱們無法作登陸的功能。不過不用擔憂,如今的咱們的前端已經很強大了。沒有後端,咱們可使用mock來模擬後端。
在安裝mock前,咱們還有一個小問題要解決,就是設置eslint的規則,默認的eslint的規則很嚴格的,咱們在頁面甚至不能使用console.log() 這就會給咱們的調試帶來困難。所以咱們要禁用一些eslint規則。
打開package.json,找到eslintConfig
項,在找到其下的rules。配置"no-console": "off"
。就能夠關閉eslint對console的限制。
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {
"no-console": "off"
},
"parserOptions": {
"parser": "babel-eslint"
}
},
複製代碼
好了,如今咱們就能夠愉快的在vue寫console了。
mock是啥呢?mock是一個測試工具。mock會攔截ajax請求並能夠按照必定規則返回數據。之前須要後臺返回給咱們的數據,如今咱們可使用mock返回了。mock的功能很強大,能夠模擬出後端的增刪改查等功能。很是方便咱們前端進行測試.
安裝
D:\test\book>yarn add mockjs
複製代碼
使用
在main.js的同級目錄下新建mock.js。咱們在mock.js裏定義剛剛咱們須要的login接口。代碼以下:
import Mock from 'mockjs'
Mock.mock('/login', 'post', (options) => {
// console.log('options:', options)
let data = JSON.parse(options.body)
let name = data.name
let password = data.password
if (name === 'admin' && password === 'admin') {
return {
status: 1,
message: '登陸成功'
}
} else {
return {
status: 0,
message: '帳號或者密碼錯誤'
}
}
})
複製代碼
這段代碼的做用即便攔截login接口請求,當帳號和密碼是admin的時候,就返回請求成功,不然返回‘帳號密碼錯誤’
如今問題來了?咱們寫好程序了,怎麼使用mock呢,其實很是簡單,簡單到我都不敢相信。咱們直接在main.js文件中引入mock.js既可。
配置
在main.js中添加以下代碼。
// 引入mock
import './mock.js'
複製代碼
ok,如今再打開咱們的login頁。輸入帳號和密碼。若是不是admin,則彈窗報錯.
若是帳號密碼正確,則跳轉到index頁面。
自此大致工做都完成了,接下來,咱們繼續完成項目(好累)。
咱們的登陸表單還有個問題,就是怎麼加驗證。表單不驗證,一來不容易發現問題,二來會頻繁的騷擾後端。本身寫驗證也能夠,可是每次都要重複寫不少代碼,鍵盤都受不了。so,仍是用組件吧,我使用的是vee-validate。
安裝:
yarn add vee-validate
複製代碼
配置:
在main.js中引入vee-validate
// 引入表單驗證
import VeeValidate, {
Validator
} from 'vee-validate'
Vue.use(VeeValidate, {
fieldsBagName: 'vee-fields'
})
// 漢化表單驗證
import zhCN from 'vee-validate/dist/locale/zh_CN'
Validator.localize('zh_CN',
zhCN)
複製代碼
修改login.vue 添加表單驗證,以用戶名爲例,個人要求是用戶名不能爲空,添加的規則以下:
<el-input v-model="form.name" v-validate="{required:true}" name="name" :class="{'is-danger':errors.has('name')}" data-vv-as="用戶名" placeholder="請輸入用戶名" ></el-input>
複製代碼
is-danger 樣式以下,把錯誤表單的邊框設置成紅色,目的是爲了突出顯示錯誤信息。至於爲何加/deep/
前綴,是由於el-input
組件是element組件,咱們在style
中設置的樣式是局部的,無法應用的到element子組件上,因此須要加上/deep/。需不須要加你本身視狀況而定。
/deep/ .is-danger input {
border-color: #ff3860;
}
複製代碼
接下來,咱們要考慮錯誤信息怎麼顯示。個人作法是直接在表單下顯示錯誤信息就能夠,缺點是若是錯誤信息不少,每一個輸入框都有一個錯誤信息的話,表單就會變得很高。
由於每一個輸入框都要顯示錯誤信息,因此我以爲把顯示錯誤信息的功能作成組件比較好,這樣能夠通用,省了不少重複代碼。
在components文件夾下新建common文件夾,再在commen文件夾下新建FormErrorMessage.vue
組件
代碼以下:
<template>
<div class="help is-danger">
<slot></slot>
</div>
</template>
<script> export default { name: 'FormErrorMessage' } </script>
<style scoped> .help { font-size: 0.75rem; margin-top: 0.25rem; line-height: 0.75rem; } .help.is-danger { color: #ff3860; } </style>
複製代碼
在Login.vue中引入
import FormErrorMessage from '../components/common/FormErrorMessage.vue'
複製代碼
在components中配置
name: 'Login',
components: {
FormErrorMessage
},
data() {
return {
form: {
name: '',
password: ''
}
}
},
複製代碼
使用
<el-form-item>
<el-input v-model="form.name" v-validate="{required:true}" name="name" :class="{'is-danger':errors.has('name')}" data-vv-as="用戶名" placeholder="請輸入用戶名" ></el-input>
</el-form-item>
<el-form-item>
<FormErrorMessage v-if="errors.has('name')">{{ errors.first('name') }}</FormErrorMessage>
</el-form-item>
複製代碼
表單驗證添加了,錯誤顯示的組件也添加了,如今只差怎麼觸發表單驗證了。很簡單,修改onSubmit函數,代碼以下,若是result爲true,則說明表單驗證經過了,不然就是有錯。
onSubmit() {
this.$validator.validate().then(result => {
if (result) {
login.submit(this.form).then(res => {
// console.log('res:', res);
if (res.data.status === 1) {
// 若是登陸成功則跳轉我index頁面
this.$router.push('/index')
} else {
// 使用element-ui的message組件,顯示登陸報錯信息
this.$message({
message: res.data.message,
type: 'error',
duration: 5000
})
}
}).catch(error => {
this.$message({
message: error,
type: 'error',
duration: 5000
})
})
}
})
},
複製代碼
添加錯誤提示後,表單樣式還須要調整下,我就不調了,結果以下:
完整Login.vue
代碼以下:
<template>
<div class="login">
<div class="l-form">
<div class="l-tip">圖書館管理系統</div>
<el-form ref="form" :model="form">
<el-form-item>
<el-input v-model="form.name" v-validate="{required:true}" name="name" :class="{'is-danger':errors.has('name')}" data-vv-as="用戶名" placeholder="請輸入用戶名" ></el-input>
</el-form-item>
<el-form-item>
<FormErrorMessage v-if="errors.has('name')">{{ errors.first('name') }}</FormErrorMessage>
</el-form-item>
<el-form-item>
<el-input v-model="form.password" type="password" v-validate="{required:true}" name="password" :class="{'is-danger':errors.has('password')}" data-vv-as="密碼" placeholder="請輸入密碼" ></el-input>
</el-form-item>
<el-form-item>
<FormErrorMessage v-if="errors.has('password')">{{ errors.first('password') }}</FormErrorMessage>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">登陸</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script> import login from '../api/login.js' import FormErrorMessage from '../components/common/FormErrorMessage.vue' export default { name: 'Login', components: { FormErrorMessage }, data() { return { form: { name: '', password: '' } } }, methods: { onSubmit() { this.$validator.validate().then(result => { if (result) { login.submit(this.form).then(res => { // console.log('res:', res); if (res.data.status === 1) { // 若是登陸成功則跳轉我index頁面 this.$router.push('/index') } else { // 使用element-ui的message組件,顯示登陸報錯信息 this.$message({ message: res.data.message, type: 'error', duration: 5000 }) } }).catch(error => { this.$message({ message: error, type: 'error', duration: 5000 }) }) } }) }, }, } </script>
<style lang="scss" scoped> .login { width: 100%; height: 100%; background: #000; .l-form { position: fixed; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%); width: 300px; margin: auto; border-radius: 8px; background: #fff; padding: 20px; .l-tip { text-align: center; font-size: 24px; font-weight: bold; } .el-form { width: 100%; margin: auto; margin-top: 20px; .el-form-item { button { width: 100%; } } } } } .is-danger input { border-color: #ff3860; } </style>
複製代碼
原本接下來該講vuex了,這裏插播一個組件js-cookie
地址:js-cookie
安裝
yarn add js-cookie
複製代碼
至於這個怎麼用,咱們稍後講vuex的時候再講解。
先在咱們終於講到最後一個知識點vuex了。爲何要用vuex,在本項目裏,使用vuex是爲了保持網站的登陸狀態。好比咱們index頁面要求用戶必須登陸纔可以訪問,這裏就要用vuex了。vuex實例化後叫store。
地址:vuex
安裝
D:\test\book>yarn add vuex
複製代碼
在store文件夾下,新建index.js文件
代碼以下:
import Vue from 'vue'
import Vuex from 'vuex'
// 引入js-cookie
import Cookies from 'js-cookie'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
name: ''
},
mutations: {
loginIn(state, name) {
state.name = name
// 設置過時時間爲1天
Cookies.set('name', name, {
expires: 1
})
},
loginOut(state) {
state.name = ''
Cookies.remove('name')
}
}
})
export default store
複製代碼
咱們定義了一個loginIn方法,調用這個方法,咱們就能夠把用戶的用戶名存在store中,同時也存在cookie裏,cookie的有效期是1天。
配置
修改main.js,把store引入進去main.js中,而後在new Vue
函數中配置
import store from './store/index.js'
……
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
複製代碼
好啦,這時候咱們就能夠愉快的使用store了。
修改Login.vue
的onSubmit
方法,用戶登陸成功後,就把用戶信息存在store中。
if (res.data.status === 1) {
// 將用戶信息存儲在vuex中
this.$store.commit('loginIn', this.form.name)
// 若是登陸成功則跳轉我index頁面
this.$router.push('/index')
} else {
……
}
複製代碼
修改Index.vue
頁面,咱們就能夠在這個頁面獲取登陸用戶的用戶名了。
Index.vue
代碼以下:
<template>
<div>這裏是Index 頁面,此時登陸的用戶是{{userName}}</div>
</template>
<style> </style>
<script> export default { name: 'Index', data() { return { } }, computed: { userName() { return this.$store.state.name } }, } </script>
複製代碼
自此,一個咱們經常使用vue項目基本上配置完成了。固然不一樣的項目,還有不一樣的組件須要安裝,到時候大家再根據狀況肯定吧。
最後再講一個關於路由攔截的問題。
如今咱們的項目已經有登陸功能了,可是並無對用戶進行限制。好比個人Index.vue頁面要求只有登陸用戶才能訪問。這時該怎麼辦呢? 這就要用路由攔截了,凡是沒有登陸的用戶要訪問Index.vue的時候,統一讓他重定向到Login頁面,讓其登陸。
修改main.js。添加以下代碼:
// 設置路由攔截
router.beforeEach((to, from, next) => {
let name = Cookies.get('name') || store.state.name
// 若是cookie沒有過時或者store中有name值,則容許訪問直接經過。不然就讓用戶登陸
if (name) {
store.commit('loginIn', name)
next()
} else {
if (to.path == '/login') {
next()
} else {
next({
name: 'Login'
})
store.commit('loginOut')
}
}
})
router.afterEach(() => {})
複製代碼
ok,如今咱們訪問Index頁面的時候就要求用戶必須登陸了。
終於,終於關於配置一個vue.3.0項目的全部內容,大概講完了。在寫這篇博客以前,我還一直髮愁該怎麼講,這麼多內容。沒想到一點點講,終於把本身想講的都講完了。
固然我講的都是簡單的使用,入門而已。若是真的作項目還須要對每一個組件都深刻了解,好比element和mock和vee-validate。大家本身去研究吧。
爲了方便查看代碼,我把整個項目上傳到了githubl了。整個項目的github地址以下:book