1. 程式人生 > >vue.js+elementUI學習01之後臺管理登入驗證實現axios和springMVC互動

vue.js+elementUI學習01之後臺管理登入驗證實現axios和springMVC互動

      前段時間學習了vue.js的一些相關知識。現在動手敲程式碼,想實現一個簡單的後臺管理,包括登入驗證、選單導航、列表、增刪改查,選單/按鈕的許可權控制等一些常見功能。當然網上也有很多例子了,只是想自己敲一遍程式碼。一直從事後臺開發,公司都是有專門的前端設計及開發的,所以本人的js/css基礎非常差,只能隨意弄弄了。

     網上找了下,這篇博文給的例子非常不錯http://www.cnblogs.com/fhen/p/6721930.html,也主要參考了下介面的實現,他的資料互動模擬是用了mock.js,本人作為後臺開發專業程式設計師,所以學習過程中,會使用spring boot快速建立一些api支援。

專案搭建  

   建立個專案admin-demo-01,這是分步驟學習的,01是登入,後面還有02,03....慢慢的一點點功能實現。

   看package.json


已經預設有vue,vue-router了,由於要使用axios作為和後臺的互動(就像jquery的ajax),element-ui作為控制元件,所以需要安裝axios/element-ui,執行命令

cnpm install axios --save

cnpm install element-ui --save


然後初始化下把整個專案都初始化npm install,然後執行起來cnpm run dev,瀏覽器訪問


登入介面

   新建立的專案,執行後訪問看到就是上面的那圖,我們需要去掉它,同時顯示我們的登入頁面,開啟App.vue,把img那去掉。


main.js修改為

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'


Vue.config.productionTip = false
Vue.use(ElementUI)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App }
})

接著,在components下建立一個Login.vue.

<template>
  <div>
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: '登入',
  data () {
    return {
      msg: 'welcome login'
    }
  }
}
</script>

router下的index.js初始是這樣的

import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello
    }
  ]
})
它預設指向components/Hello,那我們修改下
import Vue from 'vue'
import Router from 'vue-router'

// 懶載入方式,當路由被訪問的時候才載入對應元件
const Login = resolve => require(['@/components/Login'], resolve)

Vue.use(Router)

export default new Router({
    routes: [{
        path: '/',
        name: '登入',
        component: Login
    }]
})
頁面就重新整理如下圖了


  那接下來就改造登入頁:賬號輸入框、密碼輸入框、登入按鈕,Login.vue修改如下

<template>
  <el-form ref="AccountFrom" :model="account" :rules="rules" label-position="left" label-width="0px"
           class="demo-ruleForm login-container">
    <h3 class="title">系統登入</h3>
    <el-form-item prop="username">
      <el-input type="text" v-model="account.username" auto-complete="off" placeholder="賬號"></el-input>
    </el-form-item>
    <el-form-item prop="pwd">
      <el-input type="password" v-model="account.pwd" auto-complete="off" placeholder="密碼"></el-input>
    </el-form-item>
    <el-checkbox v-model="checked" checked class="remember">記住密碼</el-checkbox>
    <el-form-item style="width:100%;">
      <el-button type="primary" style="width:100%;" >登入</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: '登入',
  data () {
    return  {
        logining: false,
        account: {
          username: '',
          pwd: ''
        },
        rules: {
          username: [
            {required: true, message: '請輸入賬號', trigger: 'blur'},
            //{ validator: validaePass }
          ],
          pwd: [
            {required: true, message: '請輸入密碼', trigger: 'blur'},
            //{ validator: validaePass2 }
          ]
        },
        checked: true
      };
  }
}
</script>


<style>
  body{
    background: #DFE9FB;
  }
  .login-container{
    width:350px;
    margin-left:35%;
  }
</style>
頁面重新整理



 這時點選登入還沒有互動能力的。

axios和mock.js實現互動

  上面說了axios類似jquery的ajax。在src下建立個api資料夾,然後建立個api.js

import axios from 'axios'

axios.defaults.baseURL = 'http://127.0.0.1:80';


export const requestLogin = params => { return axios.post('/user/login', params).then(res => res.data) }


然後再建立個index.js

import * as api from './api'

export default api

這是向後臺發起請求/user/login,以post的方式。但是我們還沒做後臺服務。那這時可以使用mock.js進行攔截,然後模擬後臺服務返回的資料。

mock模式

   在src目錄下建立資料夾mock,建立檔案index.js

import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'

import { LoginUsers, users } from './data/user'

export default {

    init() {
        let mock = new MockAdapter(axios)
            // mock success request
        mock.onGet('/success').reply(200, {
            msg: 'success'
        })

        // mock error request
        mock.onGet('/error').reply(500, {
            msg: 'failure'
        })

        // 登入
        mock.onPost('/user/login').reply(arg => {
            let { username, password } = JSON.parse(arg.data)
            return new Promise((resolve, reject) => {
                let token = null


                let hasUser = LoginUsers.some(u => {
                    if (u.username === username && u.password === password) {
                        token = 'adminXXXXXX'
                        return true
                    }
                })

                if (hasUser) {
                    resolve([200, { code: 200, msg: '請求成功', token: token }])
                } else {
                    resolve([200, { code: 500, msg: '賬號或密碼錯誤' }])
                }

            })
        })



    }

}


mock下建立data資料夾,data資料夾下建立user.js

/**
 * 用來模擬使用者的一些資訊
 */
import Mock from 'mockjs'
const LoginUsers = [{
    id: 1,
    username: 'admin',
    password: '123456',
    email: '[email protected]',
    name: '程式設計師'
}]

export { LoginUsers, users }

Login.vue新增登入方法
<template>
  <el-form ref="AccountFrom" :model="account" :rules="rules" label-position="left" label-width="0px"
           class="demo-ruleForm login-container">
    <h3 class="title">系統登入</h3>
    <el-form-item prop="username">
      <el-input type="text" v-model="account.username" auto-complete="off" placeholder="賬號"></el-input>
    </el-form-item>
    <el-form-item prop="pwd">
      <el-input type="password" v-model="account.pwd" auto-complete="off" placeholder="密碼"></el-input>
    </el-form-item>
    <el-checkbox v-model="checked" checked class="remember">記住密碼</el-checkbox>
    <el-form-item style="width:100%;">
      <el-button type="primary" style="width:100%;" @click.native.prevent="handleLogin" :loading="logining" >登入</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
  import {requestLogin} from '../api/api';
  //import NProgress from 'nprogress'
  export default {
    data() {
      return {
        logining: false,
        account: {
          username: 'admin',
          pwd: '123456'
        },
        rules: {
          username: [
            {required: true, message: '請輸入賬號', trigger: 'blur'},
            //{ validator: validaePass }
          ],
          pwd: [
            {required: true, message: '請輸入密碼', trigger: 'blur'},
            //{ validator: validaePass2 }
          ]
        },
        checked: true
      };
    },
    methods: {
      handleLogin() {
        this.$refs.AccountFrom.validate((valid) => {
          if (valid) {

            this.logining = true;
            //NProgress.start();
            var loginParams = { username: this.account.username, password: this.account.pwd };
          //    let loginParams = new URLSearchParams();
          //    loginParams.append("username",this.account.username);
           //   loginParams.append("password",this.account.pwd);
            requestLogin(loginParams).then(data => {
             debugger;
              this.logining = false;
              
              let { msg, code, token } = data;
              if(code == '200'){
                //登入成功,把使用者資訊儲存在sessionStorage中
                sessionStorage.setItem('access-token', token);
                //跳轉到後臺主介面
                this.$router.push({ path: '/home' });
              }else{
                this.$message({
                  message: msg,
                  type: 'error'
                });
              }
              
            });

          } else {
            console.log('error submit!!');
            return false;
          }
        });
      }
    }
  }

</script>


<style>
  body{
    background: #DFE9FB;
  }
  .login-container{
    width:350px;
    margin-left:35%;
  }
</style>


看到登入成功後,是要跳到後臺主介面Home的,所以建立個Home.vue

<template>
  <div >
    <h1>{{ msg }}</h1>
   
  </div>
</template>

<script>
export default {
  name: '後臺主介面',
  data () {
    return {
      msg: '後臺主介面'
    }
  }
}
</script>


router下的index.js那也要修改下了
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
//import Login from '@/components/Login'
// 懶載入方式,當路由被訪問的時候才載入對應元件
const Login = resolve => require(['@/components/Login'], resolve)

Vue.use(Router)

let router = new Router({
    routes: [{
            path: '/',
            name: '登入',
            component: Login
        }, {
            path: '/login',
            name: '登入',
            component: Login
        },
        {
            path: '/home',
            name: '後臺主介面',
            component: Home
        }

    ]
})

// 訪問之前,都檢查下是否登入了
router.beforeEach((to, from, next) => {
    // console.log('to:' + to.path)
    if (to.path.startsWith('/login')) {
        window.sessionStorage.removeItem('access-token')
        next()
    } else {
        let token = window.sessionStorage.getItem('access-token')
        if (!token) {
            next({ path: '/login' })
        } else {
            next()
        }
    }
})

export default router

在main.js中引入mock

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'

import Mock from './mock'
Mock.init()

Vue.config.productionTip = false
Vue.use(ElementUI)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App }
})

初始化mockjs,axios-mock-adapter

cnpm install mockjs --save

cnpm axios-mock-adapter

最後執行cnpm run dev的時候報錯

babel-runtime/core-js/json/stringify in ./src/mock/index.js, ./~/[email protected]@babel-loader/lib!./~/[email protected]@vue-loader/lib/selector.js?typ
e=script&index=0!./src/components/Login.vue

   是使用了JSON引起的,安裝提示執行cnpm install babel-runtime --save

最後在package.json中看到的樣子


src下的檔案結構


執行起來cnpm run dev

出現登入介面,如果如果的使用者不正確(不再mock/data/user.js的LoginUsers中,則會提示賬號或密碼錯誤


如果正確,就會進入後臺主介面,如果沒登入,直接訪問主介面的url  http://localhost:8080/home,則會自動重新整理到登陸頁面

spring boot搭建後臺

  上面的程式碼,當登入的時候,發起登入請求/user/login的時候,被axios-mock-adapter攔截了,並沒有正真和後臺互動,這種模式適合純粹的前端開發階段,但最後還是要和後臺聯調的。

main.js中去掉

//import Mock from './mock'
//Mock.init()
再次登陸的時候,就無法登入了,看瀏覽器控制檯就看到404了


現在使用eclipse寫個後臺的使用者管理user-server,使用spring boot快速搭建。


UserController.java

package com.fei.springboot.controller;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.fei.springboot.controller.util.TokenUtil;

@RestController
@RequestMapping("/user")
public class UserController {

	private static Logger log = LoggerFactory.getLogger(UserController.class);
	
	@CrossOrigin(origins="*")//允許跨域請求
	@RequestMapping(value="/login",method=RequestMethod.POST)
	public JSONObject login(String username,String password,HttpServletRequest request){
		log.info("登入請求...username="+username+"  pwd=" + password);
		JSONObject r = new JSONObject();
		if("admin".equals(username) && "123456".equals(password))	{
			r.put("code", "200");
			r.put("msg", "登入成功");
			r.put("token", TokenUtil.getToken(username));
		}else{
			r.put("code", "500");
			r.put("msg", "登入失敗");
		}
		return r;
	}
	
}

其他檔案程式碼,看github上完整程式碼吧https://github.com/269941633/vue.js2.X-elementUI

好了,一切準備就緒了,點選“登入”,但是提示登入失敗了,看後臺控制檯日誌,接收到的使用者名稱和密碼是null。。。這是怎麼回事?使用postman工具測試下介面,訪問是OK的。。。趕緊百度找原因,在這篇博文中,解說得非常詳細http://www.jianshu.com/p/042632dec9fb,原因找到了,解決方法有3中。按照那博文的說法,原因就是axios判斷引數是object物件時,header中的Content-type是application/json;charset=UTF-8,而springMVC是預設application/x-www-form-urlencoded;charset=UTF-8,平時我們用jquery的ajax的時候,預設就是application/x-www-form-urlencoded;charset=UTF-8了,和後臺匹配,所以我們都不需要額外做處理。看下axios.js的原始碼


如果引數是Object,而且headers中沒有設定contentType,那就預設'application/json;charset=utf-8',把Object轉為json字串,那也就是說,如果使用axios.post的時候指定了headers的content為application/x-www-form-urlencoded;charset=UTF-8就可以了呢?試了下
api.js修改前

export const requestLogin = params => { return axios.post('/user/login', params).then(res => res.data) }
發起請求


後臺接收不到資料,修改api.js

let config = { headers: { 'content-type': 'application/x-www-form-urlencoded;charset=UTF-8' } }
export const requestLogin = params => { return axios.post('/user/login', params, config).then(res => res.data) }


request headers 中的content-type的確是變了,但是後臺仍然沒接收到資料。用postman測試


成功,檢視傳送的資訊


發現是引數,axios是json字串,而postman那是&拼接起來的。

那隻能要麼後臺接收引數的時候使用@RequestBody,要麼前臺使用URLSearchParams,

試試URLSearchParams,Login.vue,修改下

// var loginParams = { username: this.account.username, password: this.account.pwd };
              let loginParams = new URLSearchParams();
              loginParams.append("username",this.account.username);
              loginParams.append("password",this.account.pwd);
googel瀏覽器OK,但是360瀏覽器卻報Uncaught ReferenceError: URLSearchParams is not defined,網上的一些說法是URLSearchParams,並不是所有瀏覽器都支援的。

   修改後臺UserController.java

package com.fei.springboot.controller;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.fei.springboot.controller.util.TokenUtil;

@RestController
@RequestMapping("/user")
public class UserController {

	private static Logger log = LoggerFactory.getLogger(UserController.class);
	
	@CrossOrigin(origins="*")//允許跨域請求
	@RequestMapping(value="/login",method=RequestMethod.POST)
	public JSONObject login(@RequestBody Map<String,String> map){
		String username = map.get("username");
		String password = map.get("password");
		
		log.info("登入請求...username="+username+"  pwd=" + password);
		
		JSONObject r = new JSONObject();
		if("admin".equals(username) && "123456".equals(password))	{
			r.put("code", "200");
			r.put("msg", "登入成功");
			r.put("token", TokenUtil.getToken(username));
		}else{
			r.put("code", "500");
			r.put("msg", "登入失敗");
		}
		return r;
	}
	
}

這樣,後臺成功接收到axios傳的引數了。

完整原始碼

相關推薦

vue.js+elementUI學習01後臺管理登入驗證實現axiosspringMVC互動

      前段時間學習了vue.js的一些相關知識。現在動手敲程式碼,想實現一個簡單的後臺管理,包括登入驗證、選單導航、列表、增刪改查,選單/按鈕的許可權控制等一些常見功能。當然網上也有很多例子了,只是想自己敲一遍程式碼。一直從事後臺開發,公司都是有專門的前端設計及開發的

Vue.js框架學習筆記

Vue.js中的表單 可以用v-model指令在表單 <input>及 <textarea>元素上建立雙向資料繫結,它會根據控制元件型別自動選取正確的方法來更新元素。 v-model 會忽略所有表單元素的 value、checked、select

Vue.js框架學習筆記

Vue.js中的樣式繫結 class和style是HTML元素的屬性,用於設定元素的樣式,我們可以通過v-bind來設定樣式屬性,可繫結一個數據屬性或者物件。 v-bind:class="..." v-bind:style="..." class例項: <!DOCTYPE

webpack+vue.js+elementUI試做後臺管理頁面

前言 由於上次搭好了SSM後端框架,就想著順便把以前那個部落格網站的後臺管理系統給做了,系統的後端環境是有了,前端頁面用什麼開發呢?之前簡單的看了vue.js,所以就決定用vue.js做前端頁面,然後搜了一些vue.js配套的ui,找到了elementUI。而

Vue.js 基礎學習混合mixins

sda itl 實現 var title cte 混合 method ons 混合以一種靈活的方式為組件提供分布復用功能。混合對象可以包含任意的組件選項。當組件使用了混合對象時,混合對象的所有選項將被“混入”組件自己的選項中。 當混合對象與組件包含同名選項時,這些選項將以適

【轉載】Vue 2.x 實戰後臺管理系統開發(二)

null element asc 其他 就會 ans 目錄 asi all 2. 常見需求 01. 父子組件通信 a. 父 -> 子(父組件傳遞數據給子組件) 使用 props,具體查看文檔 - 使用 Prop 傳遞數據(cn.vuejs.org/v2/guide

Vue.js基礎學習npm 安裝

最近在學習.net core  的同時也在學習前端vue.js 。 從沒有接觸過一個真正的前端框架,這次打算從開始認真的學習一下。寫部落格的目的就是做下筆記。 安裝npm 下載後,雙擊安裝 。 一路next,至到安裝成功 。 開啟CMD,檢查是否正常

Vue.js基礎學習 搭建vue.js 專案框架。

還是那就俗話,寫部落格的原因就是為記筆記。其實本人也在word 文件上,也記了,但是怕丟。所以寫成部落格,當自己再需要的時候可以檢視。本人主要是c#,asp.net。為了能一人獨立開發一個完整的專案,所以學習一套前端的架構。有錯誤的地方,歡迎大家指出。不說廢話,趕緊利索的寫實

Vue實戰後臺管理系統(一)

這個系列是手把手教大家從零開始寫一個後臺管理系統,使用的技術:vuejs+vue-router+axios+vuex+element-ui+scss。 1.開發環境搭建 開始寫程式碼前準備工作要做好,包括vue開發環境,除錯工具的安裝,webstorm的配置

Vue 2.x 實戰後臺管理系統開發(一)

1. 導語 該文章將從頭到尾梳理我是如何使用 Vue 2 開發一個後臺管理專案的,我會將自己遇到的問題貼出,希望可以幫助到其他人。 2. 開發前須知 我的後臺管理系統專案運用瞭如下框架/外掛: Vue 2.x —— 專案所使用的 js 框架

Vue.js+vue-element搭建屬於自己的後臺管理模板:什麼是Vue.js?(一)

Vue.js+vue-element搭建屬於自己的後臺管理模板:Vue.js是什麼?(一) 前言 本教程主要講解關於前端Vue.js框架相關技術知識,通過學習一步一步學會搭建屬於自己的後臺管理模板,並且記錄了本人在學習過程中遇到的難題和技術要點,講解基礎知識同時分享個人所學到心得,供讀者參考與學習,學習本

JavaWeb學習入門——圖書館管理系統開發(Hibernate學習1)

pass ica void 技術分享 gets 學習 images 創建 driver 最近看了看JavaWeb的書籍,才感覺到大二時候學的JavaWeb才僅僅只是個入門。最尷尬的當初還沒咋學一直在看.NET,現在看起來JavaWeb,各種框架各種頭疼啊。看了幾個例子之後覺

vue.js初級教程--01.簡介

vue.js node.js webpack npmVue特點漸進式框架采用自底向上增量開發的設計核心庫只關註視圖層輕量級22kb min+gzip高性能渲染性能:支持條件、循環、服務端渲染方式更新性能:數據驅動、響應式特性數據驅動,支持雙向數據綁定,異步批量DOM更新組件化,支持組件獨立、組件復用以及異步加

Vue.js 基礎學習計算屬性computed

urn 同時 處理 log 添加 類型 fun new compute 我們要寫一個成績表如下 數學 90 物理 80 英語 70 <div id="app"> <table border="1"> <tr> &

vue.js實戰學習——內置指令(一)

name 初始 節點 刪除 html元素 data post 編譯 16px 註:此內容摘抄自:梁灝的《Vue.js實戰》 註:記得要引入vue.js才能運行哦,文章中貼出的代碼直接復制是不行的,html css js 都放在了一起,而且也沒有引用vue.js。 1.v

Vuex ~ 專門為vue.js設計的集中式狀態管理架構

state 原來 管理工具 t對象 包管理工具 emp UC maps fault 狀態:data中的屬性需要共享給其他vue組件使用的部分(即data中需要共用的屬性) 1、初識vuex直接來個小demo   下面操作都是基於vue-cli,如果不了解先學習下vue-

巨人大哥談電商平臺框架後臺管理框架

交易 exc 行修改 出版社 管理系 搜索 平臺 信息 自定義 巨人大哥談電商平臺框架之後臺管理框架 一級目錄 二級目錄 欄目 簡介 網站設置 基本設置 網站設置 可以自定義網站參數 系統設置 可以對系統進行相關參數設

Linux學習筆記賬號管理

去掉 linux 根據 每一個 roo 輸入密碼 人員 緩沖 table 一、用戶與組賬號 用戶賬號:包括實際人員和邏輯性對象(如應用程序執行特定工作的賬號),每一個用戶賬號包含一個唯一的用戶 ID 和組 ID,標準用戶是系統安裝過程中自動創建的用戶賬號,除 root 是

Vue.js實戰 學習筆記 一(初識Vue.js

hid dom 介紹頁面 pan 分離 name 管理 end 筆記 官方文檔中介紹:漸進式技術棧(漸進式即可以階段性地使用Vue,或者可以在使用jQuery的同時,部分模塊上使用Vue,而不是像Angular一樣一用就是全部使用) 在設計上,使用MVVM(Model-V

Vue.js實戰 學習筆記 四(v-bind及class與style綁定)

自動 turn ont === 形式 new for function href DOM元素經常動態地綁定一些class或style(比如輪播時的active) Vue.js使用v-bind指令進行對class和style多種方法的綁定:通過表達式計算出字符串結果 如筆