一、企業專案開發流程
產品提需求
互動設計出原型設計
視覺設計出UI設計圖
前端開發出頁面模板
server端存取資料庫
驗收測試
二、為什麼要使用vue:
5個前端,4個會vue,1個會react,那麼你該如何選擇
客戶要求使用vue
...
三、如何選擇腳手架
自己搭建腳手架 webpack
使用現成的腳手架
vue-cli 基於webpack 3
@vue/cli 基於webpack 4
假設電腦中裝的時@vue/cli腳手架,但是想用vue-cli的模板,可以如下安裝指令
cnpm install -g @vue/cli
cnpm install -g @vue/cli-init
四、建立專案
@vue/cli
第一種建立方式: vue create mynewapp
第二種建立方式: vue ui
第三種建立法師: vue init webpack myapp
五、開始專案配置
1、如果做的移動端,那麼需要考慮300ms延時以及點選穿透的問題,甚至是部分android手機不支援promise的解決辦法,在index.html中引入如下程式碼,如果做的是pc端,忽略此步驟
// 避免移動端真機執行雙擊螢幕會放大
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=0">
<script src=" <script> if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); } if(!window.Promise) { document.writeln('<script src="); } </script>
2、修改目錄結構
src
api
assets
components
lib
router
store
views
App.vue
main.js
3、修改App.vue結構
cnpm i node-sass sass-loader -D
<template>
<div>
<div>
<header>頭部</header>
<div>內容</div>
</div>
<footer>底部</footer>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
@import '~@/lib/reset.scss';
html, body, .container, .detailContent {
@include rect(100%, 100%); // width: 100%; height: 100%;
}
.container, .detailContent {
@include flexbox(); // display: flex
@include flex-direction(column); // flex-direction:column
.box {
@include flex();
@include rect(100%, auto);
@include flexbox();
@include flex-direction(column);
.header {
@include rect(100%, 0.44rem);
@include background-color(#f66);
}
.content {
@include flex(); // flex: 1;
@include rect(100%, auto);
@include overflow(auto);
}
}
.footer {
@include rect(100%, 0.5rem);
@include background-color(#efefef);
@include flexbox();
a {
@include flex();
@include rect(auto, 100%);
@include flexbox();
@include justify-content(); // justify-content: center;
@include align-items(); // align-items: center;
@include text-color(#333);
&.active {
@include text-color(#f66);
}
}
}
}
</style>
4、依據結構設計頁面
views/home/index.vue
views/kind/index.vue
views/cart/index.vue
views/user/index.vue
以home為例
<template>
<div>
<header>首頁頭部</header>
<div>首頁內容</div>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
5、配置路由
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'
Vue.use(Router)
export default new Router({
routes
})
router/routes.js ----- 命名檢視+命令路由+路由的懶載入+路由重定向
// 如果一個頁面不需要底部,那麼就不要傳footer,比如kind無需底部
const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'home',
components: {
default: () => import('@/views/home'),
footer: () => import('@/components/Footer')
}
},
{
path: '/kind',
name: 'kind',
components: {
default: () => import('@/views/kind'),
footer: () => import('@/components/Footer')
}
},
{
path: '/cart',
name: 'cart',
components: {
default: () => import('@/views/cart'),
footer: () => import('@/components/Footer')
}
},
{
path: '/user',
name: 'user',
components: {
default: () => import('@/views/user'),
footer: () => import('@/components/Footer')
}
}
]
export default routes
修改App.vue ---- 命名檢視(多檢視路由)default footer
<template>
<div>
<router-view></router-view>
<router-view name="footer"></router-view>
</div>
</template>
6、底部點選切換路由
components/Footer.vue,需要在App.vue中修改佈局樣式
<template>
<footer>
<ul>
<router-link tag="li" to="/home">
<span></span>
<p>首頁</p>
</router-link>
<router-link tag="li" to="/kind">
<span></span>
<p>分類</p>
</router-link>
<router-link tag="li" to="/cart">
<span></span>
<p>購物車</p>
</router-link>
<router-link tag="li" to="/user">
<span></span>
<p>我的</p>
</router-link>
</ul>
</footer>
</template>
<script>
export default {
}
</script>
7、編寫頁面
PC: element-ui
iview
移動端: mint-ui
vant
mint-ui 為例
cnpm i mint-ui -S
cnpm install babel-plugin-component -D
修改.babelrc檔案
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime",["component", [
{
"libraryName": "mint-ui",
"style": true
}
]]],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
7.1 main.js入口檔案處引入mintui
import Vue from 'vue'
import App from './App'
import router from './router'
import MintUI from 'mint-ui'
Vue.config.productionTip = false
Vue.use(MintUI)
7.2 封裝了banner.vue和prolist.vue元件
banner.vue元件中使用了UI庫 ---- 輪播圖預設佔據整個高度,提前設定好一個父容器
<template>
<div>
<mt-swipe :auto="4000">
<mt-swipe-item>11</mt-swipe-item>
<mt-swipe-item>22</mt-swipe-item>
<mt-swipe-item>33</mt-swipe-item>
</mt-swipe>
</div>
</template>
<script>
import Vue from 'vue'
import { Swipe, SwipeItem } from 'mint-ui'
Vue.use(Swipe, SwipeItem)
export default {
}
</script>
<style>
.banner {
height: 150px;
}
</style>
prolist.vue
<template>
<ul>
<li>
肖生客的救贖
</li>
</ul>
</template>
<script>
export default {
}
</script>
home/index.vue中引用元件
<template>
<div>
<header>首頁頭部</header>
<div>
<Banner />
<Prolist />
</div>
</div>
</template>
<script>
import Banner from '@/components/Banner'
import Prolist from '@/components/Prolist'
export default {
components: {
Banner,
Prolist
}
}
</script>
<style>
.banner {
height: 150px;
}
</style>
8、資料請求
cnpm i axios -S
8.1 新增mock資料功能 ----- 開發前期 ---- 後端沒有介面時這樣用
cnpm i mockjs -D
api/mock.js
// 引入mockjs
const Mock = require('mockjs')
const Random = Mock.Random
const doubandata = function () {
let articles = []
for (let i = 0; i < 10; i++) {
let newArticleObject = {
title: Random.csentence(5, 30),
thumbnail_pic_s: Random.dataImage('300x250', 'mock的圖片'),
author_name: Random.cname(),
date: Random.date() + ' ' + Random.time()
}
articles.push(newArticleObject)
}
return articles
}
// Mock.mock( url, post/get , 返回的資料);
Mock.mock('/douban', 'get', doubandata)
api/index.js
import axios from 'axios'
import { Indicator } from 'mint-ui'
const baseUrl = process.env.NODE_ENV === 'development' ? '' : '
console.log(baseUrl)
// 新增請求攔截器
axios.interceptors.request.use(function (config) {
// 在傳送請求之前做些什麼
Indicator.open()
return config
}, function (error) {
// 對請求錯誤做些什麼
Indicator.close()
return Promise.reject(error)
})
// 新增響應攔截器
axios.interceptors.response.use(function (response) {
// 對響應資料做點什麼
Indicator.close()
return response
}, function (error) {
// 對響應錯誤做點什麼
Indicator.close()
return Promise.reject(error)
})
const api = {
requestGet (url) {
return new Promise((resolve, reject) => {
axios.get(baseUrl + url)
.then(data => resolve(data.data))
.catch(err => reject(err))
})
},
requestPost (url, params) {
return new Promise((resolve, reject) => {
axios.post(baseUrl + url, params)
.then(data => resolve(data.data))
.catch(err => reject(err))
})
}
}
export default api
main.js處引入mock,專案上線以及由介面時則刪掉即可
import Vue from 'vue'
import App from './App'
import router from './router'
import MintUI from 'mint-ui'
import '@/api/mock'
8.2 假設後端已經有了介面,但是可能會存在跨域問題,如果有跨域問題,開發時需要使用到反向代理
刪掉main.js出的mock
config/index.js處配置反向代理
proxyTable: {
'/daxun': {
target: '
changeOrigin: true,
pathRewrite: {
'^/daxun': ''
}
},
},
修改api/index.js的 baseUrl地址
const baseUrl = process.env.NODE_ENV === 'development' ? '/daxun' : '
重啟伺服器,檢視效果,預期一致
9、資料處理
本元件內部處理 data
狀態管理器處理
data處理方式
home/index.vue
<template>
<div>
<header>首頁頭部</header>
<div>
<Banner />
<Prolist :prolist = "prolist"/>
</div>
</div>
</template>
<script>
import Banner from '@/components/Banner'
import Prolist from '@/components/Prolist'
import api from '@/api'
export default {
data () {
return {
bannerdata: [],
prolist: []
}
},
components: {
Banner,
Prolist
},
mounted () {
api.requestGet('/douban').then(data => {
console.log(data)
this.prolist = data
})
}
}
</script>
<style>
.banner {
height: 150px;
}
</style>
prolist.vue
<template>
<ul>
<li v-for="(item, index) of prolist" :key="index">
{{ item.title }}
</li>
</ul>
</template>
<script>
export default {
props: {
prolist: Array
}
}
</script>
mock.js修改了模擬地址,以後切換更加簡單
Mock.mock('/daxun/douban', 'get', doubandata)
以後切換mock和開發伺服器只需要新增和刪除main.js中的mock欄位即可
10、狀態管理器
cnpm i vuex -S
建立store/index.js,store/home.js,store/kind.js
index.js
import Vue from 'vue'
import VueX from 'vuex'
import home from './home'
import kind from './kind'
Vue.use(VueX)
const store = new VueX.Store({
modules: {
home,
kind
}
})
export default store
kind.js
export default {
state: {},
getters: {},
actions: {},
mutations: {}
}
home.js
import api from '@/api'
const store = {
state: {
bannerdata: [1, 2, 3],
prolist: []
},
getters: {
prolistLength (state) {
return state.prolist.length
}
},
actions: {
getprolist ({ commit }) { // 引數的解構賦值 context
api.requestGet('/douban')
.then(data => {
console.log(data)
commit('changeprolist', data) // context.commit('changeprolist', data)
}).catch(err => console.log(err))
}
},
mutations: {
changebannerdata (state, data) {
state.bannerdata = data
},
changeprolist (state, data) {
state.prolist = data
}
}
}
export default store
home/index.vue 透過mapState輔助函式可以直接獲取狀態管理器中的值,透過dispatch 觸發非同步的actions
<template>
<div>
<header>首頁頭部</header>
<div>
<Banner />
<Prolist :prolist = "prolist"/>
{{ bannerdata }}
</div>
</div>
</template>
<script>
import Banner from '@/components/Banner'
import Prolist from '@/components/Prolist'
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
bannerdata: (state) => state.home.bannerdata,
prolist: (state) => state.home.prolist
})
},
components: {
Banner,
Prolist
},
mounted () {
this.$store.dispatch('getprolist') // dispatch 一個action(非同步操作)
}
}
</script>
<style>
.banner {
height: 150px;
}
</style>
使用mapActions的等價寫法
<template>
<div>
<header>首頁頭部</header>
<div>
<Banner />
<Prolist :prolist = "prolist"/>
{{ bannerdata }}
</div>
</div>
</template>
<script>
import Banner from '@/components/Banner'
import Prolist from '@/components/Prolist'
import { mapState, mapActions } from 'vuex'
export default {
computed: {
...mapState({
bannerdata: (state) => state.home.bannerdata,
prolist: (state) => state.home.prolist
})
},
components: {
Banner,
Prolist
},
methods: {
...mapActions(['getprolist']) // 生成一個同名的函式 function getprolsit () {this.$store.dispatch('getprolist')}
},
mounted () {
this.getprolist()
}
}
</script>
<style>
.banner {
height: 150px;
}
</style>
11、列表進入詳情
編寫詳情頁面 detail/index.vue,一定要記得修改App.vue中的樣式
<template>
<div>
<div>
<header>詳情頭部</header>
<div>內容</div>
</div>
<footer>詳情底部</footer>
</div>
</template>
<script>
export default {
}
</script>
修改routes.js
{
path: '/detail/:id',
name: 'detail',
components: {
default: () => import('@/views/detail')
}
}
宣告式跳轉
prolist.vue
<router-link tag="li" :to="{name: 'detail', params: {id: item.id}}" v-for="(item, index) of prolist" :key="index">
{{ item.title }}
</router-link>
程式設計時跳轉
<li v-for="(item, index) of prolist" :key="index" @click="goDetail(item)">
{{ item.title }}
</li>
methods: {
goDetail (item) {
// this.$router.push('/detail/' + item.id)
this.$router.push({
name: 'detail',
params: {id: item.id}
})
}
}
詳情頁面可以透過 this.$route.params.id 拿到傳遞過來的資料
12、頁面切換效果
App.vue使用transition包裹router-view
<template>
<div>
<transition name="slide">
<router-view></router-view>
</transition>
<router-view name="footer"></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
@import '~@/lib/reset.scss';
html, body, .container {
@include rect(100%, 100%); // width: 100%; height: 100%;
}
.container {
max-width: 640px;
margin: 0 auto;
box-shadow: 0 0 2px #ccc;
@include flexbox(); // display: flex
@include flex-direction(column); // flex-direction:column
.box {
@include flex();
@include rect(100%, auto);
@include flexbox();
@include flex-direction(column);
.header {
@include rect(100%, 0.44rem);
@include background-color(#f66);
}
.content {
@include flex(); // flex: 1;
@include rect(100%, auto);
@include overflow(auto);
}
}
.footer {
@include rect(100%, 0.5rem);
@include background-color(#efefef);
ul {
@include rect(100%, 100%);
@include flexbox();
li {
@include flex();
@include rect(auto, 100%);
@include flexbox();
@include justify-content(); // justify-content: center;
@include align-items(); // align-items: center;
@include text-color(#333);
&.router-link-exact-active,.router-link-active{
@include text-color(#f66);
}
}
}
}
}
.slide-enter {
transform: translateX(100%);
}
.slide-enter-active {
transition: all .3s;
}
.slide-enter-to {
transform: translateX(0%);
}
.slide-leave {
transform: translateX(0%);
}
.slide-leave-active {
transition: all 0s;
}
.slide-leave-to {
transform: translateX(-100%);
}
</style>
13、下拉重新整理以及上拉載入功能
以分類為例
<template>
<div>
<header>分類頭部</header>
<div>
<mt-loadmore :top-method="loadTop" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded" ref="loadmore">
<ul>
<li v-for="(item, index) of kindlist" :key="item.id">{{ item.title }} --- {{ index }}</li>
</ul>
</mt-loadmore>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Loadmore } from 'mint-ui'
import api from '@/api'
Vue.use(Loadmore)
export default {
data () {
return {
kindlist: [],
allLoaded: false, // 所有的資料是否已經載入完畢
pageCode: 1 // 頁碼
}
},
mounted () { // 請求一次資料
api.requestGet('/douban')
.then(data => {
this.kindlist = data
})
},
methods: {
loadTop () { // 下啦重新整理函式 --- 請求了第一頁的資料
api.requestGet('/douban')
.then(data => {
this.kindlist = data // 替換資料
this.pageCode = 1 // 重新整理完畢,頁碼歸1
this.allLoaded = false // 重新整理完畢,表示可以繼續載入下一頁
this.$refs.loadmore.onTopLoaded() // 更新列表
})
},
loadBottom () {
api.requestGet('/douban?count=20&start=' + this.pageCode * 20)
.then(data => {
if (data.length === 0) { // 沒有資料的條件
this.allLoaded = true// 若資料已全部獲取完畢
}
this.pageCode += 1 // 頁碼加一,下一次請求資料時用
this.kindlist = [...this.kindlist, ...data] //組合資料
this.$refs.loadmore.onBottomLoaded() // 更新列表
})
}
}
}
</script>
<style>
.kindlist {
li {
height: 40px;
border-bottom: 1px solid #ccc;
line-height: 40px;
}
}
</style>
如果想要結合vuex實現
kind/index.vue
<template>
<div>
<header>分類頭部</header>
<div>
<mt-loadmore :top-method="loadTop" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded" ref="loadmore">
<ul>
<li v-for="(item, index) of kindlist" :key="item.id">{{ item.title }} --- {{ index }}</li>
</ul>
</mt-loadmore>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Loadmore } from 'mint-ui'
import { mapState } from 'vuex'
Vue.use(Loadmore)
export default {
data () {
return {
allLoaded: false,
pageCode: 1
}
},
computed: {
...mapState({
kindlist: (state) => state.kind.kindlist
})
},
mounted () {
this.$store.dispatch('getkindlist')
},
methods: {
loadTop () {
this.$store.dispatch('loadTop').then(() => {
this.pageCode = 1
this.allLoaded = false
this.$refs.loadmore.onTopLoaded()
})
},
loadBottom () {
this.$store.dispatch('loadBottom', { pageCode: this.pageCode }).then(data => {
if (data.length === 0) {
this.allLoaded = true
} else {
this.pageCode += 1
}
this.$refs.loadmore.onBottomLoaded()
})
}
}
}
</script>
<style>
.kindlist {
li {
height: 40px;
border-bottom: 1px solid #ccc;
line-height: 40px;
}
}
</style>
store/kind.js
import api from '@/api'
export default {
state: {
kindlist: []
},
getters: {},
actions: {
getkindlist ({ commit }) {
api.requestGet('/douban')
.then(data => {
commit('changekindlist', data)
})
},
loadTop ({ commit }) {
return new Promise((resolve, reject) => {
api.requestGet('/douban')
.then(data => {
commit('changekindlist', data)
resolve()
})
})
},
loadBottom ({ commit, state }, params) {
console.log(params)
return new Promise((resolve, reject) => {
api.requestGet('/douban?count=20&start=' + params.pageCode * 20)
.then(data => {
console.log('bottom', data)
const arr = [...state.kindlist, ...data]
console.log('arr', arr)
commit('changekindlist', arr)
resolve(data)
})
})
}
},
mutations: {
changekindlist (state, data) {
state.kindlist = data
}
}
}
14、回到頂部
components/BackTop.vue
<template>
<span @click="backtop">返回頂部</span>
</template>
<script>
export default {
methods: {
backtop () {
console.log('1')
document.getElementById('content').scrollIntoView()
}
}
}
</script>
<style>
.backtop {
position:fixed;
right:10px;bottom:60px;
}
</style>
使用時可以給需要的地方新增一個
<div id="content"></div>
15、購物車業務邏輯
<template>
<div>
<header>購物車頭部</header>
<div>
<input type="checkbox" v-model="allChecked" @change="test">
<ul>
<li v-for="(item, index) of cartlist" :key="index">
<input type="checkbox" v-model="item.flag" @change="fn(item)"/>
{{ item.name }}
<button @click="item.num-=1">-</button> {{ item.num }} <button @click="item.num+=1">+</button>¥{{ item.price }} 小計: {{ item.num * item.price}}
</li>
</ul>
<h1>總數為:{{ totalNum }}</h1>
<h1>總價為:{{ totalprice }}</h1>
</div>
</div>
</template>
<script>
export default {
data () {
return {
allChecked: false,
cartlist: [
{
id: 1,
name: '蘋果',
price: 4.8,
num: 2,
flag: false
},
{
id: 2,
name: '香蕉',
price: 3,
num: 5,
flag: false
},
{
id: 3,
name: '榴蓮',
price: 29.8,
num: 1,
flag: false
}
]
}
},
methods: {
test () {
if (this.allChecked) {
this.cartlist.map(item => {
item.flag = true
})
} else {
this.cartlist.map(item => {
item.flag = false
})
}
},
fn (item) {
if (!item.flag) {
this.allChecked = false
} else {
let bool = true
this.cartlist.map(item => {
if (!item.flag) {
bool = false
}
})
this.allChecked = bool
}
}
},
computed: {
totalNum () {
let num = 0
this.cartlist.map(item => {
item.flag ? num += item.num : num += 0
})
return num
},
totalprice () {
let price = 0
this.cartlist.map(item => {
item.flag ? price += item.num * item.price : price += 0
})
return price.toFixed(2)
}
},
watch: {
allChecked (newVal) {
}
}
}
</script>
<style>
</style>
16、註冊功能 --- 計算屬性
<template>
<div>
<header>註冊</header>
<div>
<mt-field placeholder="請輸入使用者名稱" :state="usernameState" v-model="username"></mt-field>
<mt-field placeholder="請輸入密碼" type="password" v-model="password" :state="passwordState"></mt-field>
<mt-field placeholder="驗證碼" v-model="code" :state="codeState">
<mt-button @click="sendCode" :disabled="sendState">{{msg}}</mt-button>
</mt-field>
<mt-button :disabled="disabledtype" @click="register" :type="type" size="large">註冊</mt-button>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Field, Button } from 'mint-ui'
import api from '@/api'
Vue.use(Field, Button)
export default {
data () {
return {
username: '17733203950',
password: '123456',
msg: '傳送驗證碼',
time: 10,
sendState: false,
code: '',
adminCode: ''
}
},
computed: {
usernameState () {
if (this.username === '') {
return ''
} else if (/^[1][3,4,5,6,7,8,9][0-9]{9}$/.test(this.username)) {
return 'success'
} else {
return 'error'
}
},
passwordState () {
if (this.password === '') {
return ''
} else if (this.password.length > 5) {
return 'success'
} else {
return 'error'
}
},
codeState () {
if (this.code === '') {
return ''
} else if (this.code === this.adminCode) {
return 'success'
} else {
return 'error'
}
},
disabledtype () {
if (this.usernameState === 'success' && this.passwordState === 'success' && this.codeState === 'success') {
return false
}
},
type () {
if (this.usernameState === 'success' && this.passwordState === 'success' && this.codeState === 'success') {
return 'primary'
} else {
return 'default'
}
}
},
methods: {
getCode () {
api.requestGet('/users/sendCode?tel=' + this.username)
.then(data => {
if (data === 0) {
console.log('驗證碼傳送失敗')
} else if (data === 1) {
console.log('手機號已經註冊過')
} else {
console.log(data)
this.adminCode = data.code
}
})
},
sendCode () {
console.log('傳送簡訊驗證碼')
this.sendState = true
this.getCode()
var timer = setInterval(() => {
this.msg = this.time + '後重新傳送'
this.time--
if (this.time === -1) {
this.msg = '傳送驗證碼'
this.sendState = false
this.time = 10
clearInterval(timer)
}
}, 1000)
},
register () {
api.requestPost('/users/register', {
username: this.username,
password: this.password
}).then(data => {
if (data === 0) {
console.log('註冊失敗')
} else if (data === 1) {
console.log('註冊成功')
} else {
console.log('使用者名稱已註冊')
}
})
}
}
}
</script>
<style>
</style>
登入
<template>
<div>
<header>登入</header>
<div>
<mt-field placeholder="請輸入使用者名稱" :state="usernameState" v-model="username"></mt-field>
<mt-field placeholder="請輸入密碼" type="password" v-model="password" :state="passwordState"></mt-field>
<mt-button :disabled="disabledtype" @click="login" :type="type" size="large">登入</mt-button>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { Field, Button } from 'mint-ui'
import api from '@/api'
Vue.use(Field, Button)
export default {
data () {
return {
username: '17733203950',
password: '123456'
}
},
computed: {
usernameState () {
if (this.username === '') {
return ''
} else if (/^[1][3,4,5,6,7,8,9][0-9]{9}$/.test(this.username)) {
return 'success'
} else {
return 'error'
}
},
passwordState () {
if (this.password === '') {
return ''
} else if (this.password.length > 5) {
return 'success'
} else {
return 'error'
}
},
disabledtype () {
if (this.usernameState === 'success' && this.passwordState === 'success') {
return false
}
},
type () {
if (this.usernameState === 'success' && this.passwordState === 'success') {
return 'primary'
} else {
return 'default'
}
}
},
methods: {
login () {
api.requestPost('/users/login', {
username: this.username,
password: this.password
}).then(data => {
if (data === 0) {
console.log('登入失敗')
} else if (data === 1) {
console.log('登入成功')
// 登入成功,還可以返回token資訊,把它儲存到本地
// 以後請求資料時,把token攜帶過去
localStorage.setItem('isLogin', 'ok')
} else if (data === 2) {
console.log('使用者未註冊')
} else {
console.log('密碼錯誤')
}
})
}
}
}
</script>
<style>
</style>