且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

VUE学习笔记(终)

更新时间:2022-02-13 11:39:55

十三、使用Axios发送请求


13.1 什么是 Axios

Axios 是一个开源的可以用在浏览器端和 NodeJS 的异步通信框架,她的主要作用就是实现 AJAX 异步通信,其功能特点如下:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF(跨站请求伪造)

GitHub:https://github.com/axios/axios

13.2 为什么要使用 Axios

由于 Vue.js 是一个 视图层框架 并且作者(尤雨溪)严格准守 SoC (关注度分离原则),所以 Vue.js 并不包含 AJAX 的通信功能,为了解决通信问题,作者单独开发了一个名为 vue-resource 的插件,不过在进入 2.0 版本以后停止了对该插件的维护并推荐了 Axios 框架

13.3 Axios的使用

13.3.1 安装vue axios
npm install --save axios vue-axios
13.3.2 在main.js中引入

在项目中使用axios模块

import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios)
13.3.3 发送ajax请求
<template>
  <div id="app">
    <div style="width:50%" class="container">
      <div>
        <h3>Regist</h3>
        <h5>Email</h5>
        <input type="text" class="form-control" v-model="mail" /><br />
        {{mail}}
        <h5>Password</h5>
        <input type="password" class="form-control" v-model="password" /><br />
        {{password}}
        <h5>Gender</h5>
        <input type="radio" name="gender" v-model="gender" value="female" />男
        <input type="radio" name="gender" v-model="gender" value="male" />女<br />
        <h5>Hobby</h5>
        <input type="checkbox" name="hobby" v-model="hobby" value="music">音乐
        <input type="checkbox" name="hobby" v-model="hobby" value="movie">电影
        <input type="checkbox" name="hobby" v-model="hobby" value="sport">运动
        <br/>
        <button type="button" class="btn btn-success" @click="registfn">注册</button>
      </div>
    </div>
  </div>
</template>

<script>
  import MHeader from './components/Header'
export default {
  name: 'app',
  data(){
    return {
      mail:'',
      password:'',
      gender:'',
      hobby:''
    }

  },
  methods:{
    registfn:function(){

      this.axios({
        method:'get',
        url:'http://localhost:8090/regist?mail='+this.mail+'&password='+this.password,

      }).then(function (response) {
        console.log(response.data)
      });
    }
  }
}
</script>
13.3.4 服务端解决跨域问题
<mvc:cors>  
    <mvc:mapping path="/"
        allowed-origins="*"
        allowed-methods="POST, GET, OPTIONS, DELETE, PUT,PATCH"
        allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
        allow-credentials="true" />
</mvc:cors>

在spring-mvc.xml中加入上述这一段。其中,allowed-origins指的是允许的访问源的域名,"*"表示任何人都可以访问,也可以指明具体的域名

13.3.5 解决axios无法传递data中的参数问题

原因:默认情况下发送axios时请求头中的内容类型为: (后端没有使用@RequestBody)

Content-Type:application/json;charset=UTF-8

而实际服务端需要的是:

Content-Type:application/x-www-form-urlencoded

因此,使用axios的qs内置库中的方法进行内容类型的转换。

import Qs from 'qs'

this.axios({
    method:'post',
    url:'http://localhost:8081/regist',
    transformRequest: [function (data) {
        return Qs.stringify(data)
    }],
    data:{
        email:this.email
    }
})
.then(function (response) {
    alert(response.data.message)
});

十四、Vue实战项目:Webpack登录验证后路由至列表页


对项目进行中的内容进行调整,结构如下:
VUE学习笔记(终)
各部分内容:

14.1 router路由模块: index.js(路由配置表)

import Vue from 'vue'
import Router from 'vue-router'

import Login from '../views/Login'
import Home from '../views/Home'



// 安装路由
Vue.use(Router);

// 配置路由
export default new Router({
  routes: [
    {
      // 路由路径
      path: '/Login',
      // 路由名称
      name: 'Login',
      // 跳转到组件
      component: Login
    },
    {
      path:'/Home',
      name:'Home',
      component:Home
    }
  ]
});

14.2 使用Element-UI组件库

14.2.1 安装
在项目文件夹内使用命令来安装element-ui模块
npm i element-ui -S
14.2.2 使用
在vue项目中引入element-ui并使用。在 main.js 中写入以下内容:
import Vue from 'vue';
import ElementUI from 'element-ui'; //加入
import 'element-ui/lib/theme-chalk/index.css';//加入
import App from './App.vue';

Vue.use(ElementUI);//加入

new Vue({
  el: '#app',
  render: h => h(App)
});
14.2.3 在Element-UI组件库中查找组件
在官方组件库中,根据需求找到组件,然后在项目中使用。
VUE学习笔记(终)

14.3 编写登录组件:Login.vue

<template>
    <div class="login-box">
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <h3>欢迎登录</h3>
        <el-form-item label="用户名" prop="name">
          <el-input v-model="form.name" placeholder="请输入用户名"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input type="password" v-model="form.password" placeholder="请输入密码"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit('form')">登录</el-button>
        </el-form-item>
      </el-form>
    </div>
</template>

<script>
export default {
    name: "Login",
    data(){
      return{
        form:{
          name:'',
          password:''
        },
        rules:{
          name:[
            { required: true, message: '请输入用户名', trigger: 'blur' },
            { min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
          ],
          password:[
            { required: true, message: '请输入密码', trigger: 'blur' },
            { min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
          ]
        }
      }

    },
    methods:{
      onSubmit(formName){
        this.$refs[formName].validate((valid) => {
          var vm = this;
          if (valid) {
            // 发送axios请求
            this.axios({
              method:'post',
              url:'http://localhost:8090/login',
              data:{
                name:vm.form.name,
                password:vm.form.password
              }
            }).then(function(resp){
              // console.log(resp.data)
              if(resp.data.errno==0){

                //登录成功,要向vuex中存放user对象
                var user  = resp.data.data;
                vm.$store.dispatch('asyncUpdateUser', user);
                vm.$message({
                  message: '登录成功',
                  type: 'success'
                });
                setTimeout(function(){
                  vm.$router.push("/Home")
                },2000)
              }else{
                vm.$message.error('用户名或密码错误');
              }
            })

          } else {
            this.$message.error('用户名或密码格式错误');
            return false;
          }
        });
      }
    }
}
</script>

<style scoped>
  .login-box{
    width: 500px;
    height: 300px;
    border: 1px solid #DCDFE6;
    margin: 150px auto;
    padding: 20px 50px 20px 30px;
    border-radius: 20px;
    box-shadow: 0px 0px 20px #DCDFE6;
  }
</style>

输入的用户名和密码,通过Axios请求去后端做校验,若校验成功则路由至Home组件。
登录页面的展示效果:(Element UI)
VUE学习笔记(终)

14.4 编写入口js:main.js

import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// 导入上面创建的路由配置表
import router from './router'

// 导入ElementUI模块
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.use(VueRouter);

// 使用ElementUI模块
Vue.use(ElementUI);
// 使用Axios (vue中实现ajax功能的组件)
Vue.use(VueAxios, axios)



Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  // 配置路由
  router,
  render: h => h(App)
})

十五、 Vuex的应用


15.1 什么是Vuex

Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

15.2 安装

在项目根目录执行如下命令来安装 Vuex

若失败,可使用cnpm

npm install vuex --save
修改 main.js 文件,导入 Vuex,关键代码如下:
import Vuex from 'vuex'
Vue.use(Vuex);

15.3 配置 vuex

15.3.1 创建 Vuex 配置文件
在 src 目录下创建一个名为 store 的目录并新建一个名为 index.js 文件用来配置 Vuex,代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);

// 全局 state 对象,用于保存所有组件的公共数据
const state = {
  // 定义一个 user 对象
  // 在组件中是通过 this.$store.state.user 来获取
  user: {
    name: ''
  }
};

// 实时监听 state 值的最新状态,注意这里的 getters 可以理解为计算属性
const getters = {
  // 在组件中是通过 this.$store.getters.getUser 来获取
  getUser(state) {
    return state.user;
  }
};

// 定义改变 state 初始值的方法,这里是唯一可以改变 state 的地方,缺点是只能同步执行
const mutations = {
  // 在组件中是通过 this.$store.commit('updateUser', user); 方法来调用 mutations
  updateUser(state, user) {
    state.user = user;
  }
};

// 定义触发 mutations 里函数的方法,可以异步执行 mutations 里的函数
const actions = {
  // 在组件中是通过 this.$store.dispatch('asyncUpdateUser', user); 来调用 actions
  asyncUpdateUser(context, user) {
    context.commit('updateUser', user);
  }
};

export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions
});
修改 main.js 增加刚才配置的 store/index.js,关键代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
import store from './store'

Vue.use(Vuex);

new Vue({
  el: '#app',
  store
});
15.3.2 解决浏览器刷新后 Vuex 数据消失问题
  • 问题描述
Vuex 的状态存储是响应式的,当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。但是有一个问题就是:vuex 的存储的数据只是在页面的中,相当于我们定义的全局变量,刷新之后,里边的数据就会恢复到初始化状态。但是这个情况有时候并不是我们所希望的。
  • 解决方案
监听页面是否刷新,如果页面刷新了,将 state 对象存入到 sessionStorage 中。页面打开之后,判断 sessionStorage 中是否存在 state 对象,如果存在,则说明页面是被刷新过的,将 sessionStorage 中存的数据取出来给 vuex 中的 state 赋值。如果不存在,说明是第一次打开,则取 vuex 中定义的 state 初始值。
  • 修改代码
在 App.vue 中增加监听刷新事件
  export default {
    name: 'App',
    mounted() {
      window.addEventListener('unload', this.saveState);
    },
    methods: {
      saveState() {
        sessionStorage.setItem('state', JSON.stringify(this.$store.state));
      }
    }
  }
修改 store/index.js 中的 state
const state = sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : {
  user: {
    name: ''
  }
};