• vue实战(4):postman测试数据、封装ajax、使用vuex管理状态


    书到用时方恨少

    这个阶段涉及到了vuex,本来想着不慌,用起来,使用的过程中问题还真不少
    本篇涉及到的内容:
    ---postman 测试数据
    ---封装 ajax 请求函数
    ---封装接口请求函数
    ---使用 vuex 管理状态
    ---获取首页相关数据

    0. 其它

    vue实战(1):准备与资料整理
    vue实战(2):初始化项目、搭建底部导航路由
    vue实战(3):底部导航显示、搭建各模块静态页面、添加登录页页面与路由
    vue实战(4):postman测试数据、封装ajax、使用vuex管理状态
    vue实战(5):总结一
    vue实战(6):异步显示数据、开发Star组件
    vue实战(7):完整开发登录页面(一)
    vue实战(8):完整开发登录页面(二)
    vue实战(9):总结二
    vue实战(10):开发店铺详情(一)

    1. 安装 MongoDB ,启动后台

    • 这个小练习项目是一个前后台分离的项目,后台应用负责处理前台应用提交的请求, 并给前台应用返回 json 数据,前台应用负责展现数据, 与用户交互, 与后台应用交互。
      • 后台应用是用nodejs写的,数据库需要用到mongodb
      • 暂时不会nodejsmongodb,不过没关系,照着文档先用起来,问题不大。
      • MongoDB 官方网站链接 和 教程与安装链接
    1.1 到MongoDB官网,下载适合的版本,安装好
    1.2 到后台项目文件夹下,cmd,用npm start启动数据库
    

    启动数据库

    2. 使用 postman 测试数据

    • 数据库打开以后,进一步去测试是否打开成功,是否能取到数据,这里就要用到接口测试工具 postman
    • postman 可以获取数据、可以检测API文档中的接口是否有问题
    • 项目重点也不在这里,可以去 postman 官方网站链接 下载客户端 和 很厉害的教程链接
    • 查看API接口文档
    1.1 根据经纬度获取位置详情(例子)
        --请求URL:http://localhost:3000/position/:geohash
        --示例:http://localhost:3000/position/40.10038,116.36867
        --请求方式:GET
        --参数类型:param
        |参数		  |是否必选   |类型       |说明
    	|geohash    |Y         |string    |经纬度
        --返回示例:
        {
          "code": 0,
          "data": {
            "address": "北京市昌平区337省道",
            "city": "北京市",
            "geohash": "40.10038,116.36867",
            "latitude": "40.10038",
            "longitude": "116.36867",
            "name": "昌平区北七家宏福科技园(337省道北)"
            }
         }
    1.2 接口输入postman中,查看结果
    1.3 输出与文档相同,获取数据成功
    

    数据获取成功

    3. 封装 ajax 请求函数

    • 这里的异步交互使用的是axios,需要在项目中添加依赖 npm install --save axios
    • 这里的封装非常重要,虽然代码不是很难懂,但是感觉是 知其然而不知其所以然 ,这也是贯彻了模块化开发的思想,还是先用起来,会熟能生巧的。
      • api 文件夹下创建 ajax.js ,引入 axiosimport axios from 'axios'
    import axios from 'axios'
    /*
     ajax请求模块
     封装ajax请求函数
     */
    export default function ajax (url = '', data = {}, type = 'GET') { // type 默认传 get
      return new Promise(function (resolve, reject) { // 返回 new promise,后面会用到 async 和 await
        let promise
        if (type === 'GET') { // 判断 get
          let dataStr = '' // 数据拼接字符串
          Object.keys(data).forEach(key => {
            dataStr += key + '=' + data[key] + '&'
          })
          if (dataStr !== '') { // 拼接成 url 地址
            dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
            url = url + '?' + dataStr
          }
          // 发送get请求
          promise = axios.get(url)
        } else {
          // 发送post请求
          promise = axios.post(url)
        }
        promise.then(response => {
          resolve(response.data)
        })
          .catch(error => {
            reject(error)
          })
      })
    }
    

    4. 封装接口请求函数

    • ajax 请求封装完成之后,就是开始封装各个接口请求函数
      • api 文件夹下创建 index.js ,引入 ajaximport ajax from './ajax'
    • 这个就好理解的多,根据项目需求的不同,需要的接口会非常的多,这样做也是模块化的体现,便于管理和维护
    /* 包含多个模块ajax函数
    * 封装接口请求函数(一部分例子)
    * */
    import ajax from './ajax'
    const BASE_URL = '/api'  // 关于跨域
    
    // 1、根据经纬度获取位置详情
    // 此处直接这么写,当请求时会出错,因为后台代码的端口是4000(或域名),与本地的请求端口不一致,自然无法实现跨域ajax请求,需要代理配置
    // export const reqAddress = (geohash) => ajax(`/position/${geohash}`) 
    export const reqAddress = (geohash) => ajax(`${BASE_URL}/position/${geohash}`)
    // 2、获取食品分类列表
    export const reqCategorys = () => ajax(`${BASE_URL}/index_category`)
    // 3、根据经纬度获取商铺列表
    export const reqShops = (latitude, longitude) => ajax(`${BASE_URL}/shops`, { latitude, longitude })
    
    • 此处涉及到跨域的问题,需要进行一些配置
      • 因为本项目使用vue-cli3脚手架搭建,没有现成的配置文件,现在需要在根目录下创建 vue.config.js,查了一些资料,有点杂而且比较落后,其中一些参数已经被弃用了,配置了一个简洁的,其它配置可以看 官方文档
    // vue.config.js
    module.exports = {
      // 修改的配置
      publicPath: '/',
      devServer: {
        proxy: {
          '/api': { // 匹配所有以 '/api'开头的请求路径
            target: 'http://localhost:4000', // 代理目标的基础路径
            changeOrigin: true, // 支持跨域
            // ws: true,
            pathRewrite: { // 重写路径: 去掉路径中开头的'/api'
              '^/api': ''
            }
          }
        }
      }
    }
    
    • 配置完成,测试一下是否能够取到数据,可以在 App.vue 中引入 import { reqCategorys } from './api',添加mounted方法
    async mounted () {  // 例子
        const result = await reqCategorys()
        console.log(result) // 打印输出
      }
    

    数据获取成功

    5. 创建 vuex 整体结构,管理状态

    关于vuex的学习,起初不是怎么会用,看了官方文档也没怎么懂,看了几篇博客知道了一些使用方法,视频中对这部分的构建还是去年的形式,我照着现在的形式搭建了一下,因为只知其一不知其二,这也造成一些问题,好在目前遇到的问题都解决了,问题不大,后面还需要继续深入学习。
    modules文件夹里面放模块,更便于管理与维护

    • 首先是下载依赖,并且在main.js中配置好 import store from './store/store',并且在store.js中引用import Vuex from 'vuex'和使用Vue.use(Vuex)
      • 如果在创建项目时已经配置好 vuex ,则无需在main.js中配置,已经是配置好的了
    // vuex最核心的管理对象store
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    // 引用模块
    import msite from './modules/msite' 
    import getters from './getters'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      modules: {
        msite // modules文件夹中的msite模块
      },
      getters
    })
    
    
    • 模块的编写(例子)
    // 内容比较多,这边可以把相似或者功能相同的组成一个模块,更方便维护
    // 模块文件在store.js中引用
    
    import { // 引用封装好的接口
      reqAddress,
      reqCategorys,
      reqShops
    } from '../../api/index'
    
    // 基础数据状态,现在在任何文件都可以引用,引用时 this.$store.xxx 即可
    const state = {
      latitude: 40.10038, // 纬度
      longitude: 116.36867, // 经度
      address: {}, // 地址信息对象
      categorys: [], // 分类数组
      shops: [] // 商家数组
    }
    
    // 直接更改state的多个方法的对象,现在在任何文件都可以引用,引用时 this.$store.commit('xxxx')即可
    const mutations = { 
      RECEIVE_ADDRESS: (state, { address }) => { // 接受地址
        state.address = address
      },
      RECEIVE_REQCATEGORYS: (state, { categorys }) => { // 接受食品分类数组
        state.categorys = categorys
      },
      RECEIVE_REQSHOPS: (state, { shops }) => { // 接受商家数组
        state.shops = shops
      }
    }
    
    // 与后台交互的数据,现在在任何文件都可以引用,引用时 this.$store.dispatch('xxxx')即可
    const actions = {
      // 异步获取地址
      async getAddress ({ commit, state }) {
        // 发送ajax异步请求
        const geohash = state.latitude + ',' + state.longitude
        const result = await reqAddress(geohash)
        // 提交一个mutations
        if (result.code === 0) {
          commit('RECEIVE_ADDRESS', { address: result.data })
        }
      },
      // 异步获取分类列表
      async getCategorys ({ commit }) {
        const result = await reqCategorys()
        if (result.code === 0) {
          commit('RECEIVE_REQCATEGORYS', { categorys: result.data })
        }
      },
      // 异步获取商家列表
      async getShops ({ commit, state }) {
        const { latitude, longitude } = state
        const result = await reqShops({ latitude, longitude })
        if (result.code === 0) {
          commit('RECEIVE_REQSHOPS', { shops: result.data })
        }
      }
    }
    
    export default { // 把方法暴露出去
      namespaced: true,
      state,
      mutations,
      actions
    }
    
    
    • vuex 构建好,下面是使用测试,在需要的地方使用
      • 这里还涉及到了 vuex 的辅助函数,mapStatemapMutationsmapActionvuex最简单、最详细的入门文档,这篇文章写的非常好,具体的就不展开了,直接使用起来,问题不大。
      • 首先在App.vue中引入import { mapActions } from 'vuex',使用需要的方法
    <script>
    import FooterGuide from './components/FooterGuide/FooterGuide'
    import { mapActions } from 'vuex'
    export default {
      name: 'App',
      mounted () {
        // this.$store.dispatch('msite/getAddress')
        this.getAddress() // 这边调用的方法,在浏览器的插件中会有一个非常清楚的展示
      },
      methods: {
        ...mapActions('msite', ['getAddress'])
      },
      components: {
        FooterGuide
      }
    }
    </script>
    

    getAddress方法更改数据后存在于mutation

    • 现在我们需要其中的 name 属性数据,在Msite.vue中引用import { mapState } from 'vuex',添加 computed 方法:computed: { ...mapState('msite', ['address'])},然后就可以愉快的使用了
    <!--首页头部-->
    <!--此处title使用强制绑定,取出 address 中的 name-->
        <HeaderTop :title = "address.name"> 
          <router-link class="header_search" slot="left" to="">
            <i class="iconfont iconfangdajing"></i>
          </router-link>
          <router-link class="header_login" slot="right" to="">
            <span class="header_login_text">登录|注册</span>
          </router-link>
        </HeaderTop>
    

    state中的数据
    取出name属性并显示

    6. 结束

    感觉这个部分是最难的部分了,还是不熟悉的原因,下面都是逻辑处理方面的内容了

    点个赞呗!

  • 相关阅读:
    netty(八) netty中自带channelhandler
    netty(七) Handler的执行顺序
    netty(六) websocket开发应用
    netty(五) http协议开发应用
    netty(四) 编解码技术
    netty(三) TIP黏包/拆包问题解决之道
    netty(二) 创建一个netty服务端和客户端
    netty(一) netty有哪几部分构成
    使用jsp制作index,可以通过<c:if test==“管理员”>或<c:if test=="客户">来区别展示用户界面
    使用jstl和el表达式来展示request域中存放的user对象的信息
  • 原文地址:https://www.cnblogs.com/jry199506/p/11040117.html
Copyright © 2020-2023  润新知