zl程序教程

您现在的位置是:首页 >  前端

当前栏目

vue前台(四点一)

Vue 前台
2023-09-11 14:20:08 时间

一,mockjs模拟banner和floor接口操作,组件获取数据

1.创建mock文件夹,创建banner.json和floor.json, mockServer.js(提供服务,模拟接口)    安装mockjs  npm  i  mockjs

mockServer.js 文件内容

//正儿八经的模拟接口
import Mock from 'mockjs'
import banner from './banner.json'  //json数据被引入之后会变为真正的数组,不再是json串了
import floor from './floor.json'  //json数据被引入之后会变为真正的数组,不再是json串了

//第一个参数,是以后我们要请求的模拟接口路径
//第二个参数,是访问这个接口后返回的数据
//   '/mock/banner'   /mock不能省,因为这个并不是去发送ajax请求,
// 发请求可以省,是因为我们在axios配置了baseUrl
// 这个不是发请求,是模拟整个接口
Mock.mock('/mock/banner',{code:200,data:banner})
Mock.mock('/mock/floor',{code:200,data:floor})

//最后切记在入口文件去引入一下,代表这个文件一开始就会执行

2.在入口文件main.js导入mock,    

import '@/mock/mockServer'
 
3.在 ajax文件夹中新建mockAjax.js, 二次封装关于mock的ajax
 
mockAjax.js文件内容
//对axios的二次封装
// 配置基础路径和超时限制
// 添加进度条信息  nprogress
// 返回的响应不再需要从data属性当中拿数据,而是响应就是我们要的数据
// 统一处理请求错误, 具体请求也可以选择处理或不处理
import axios from 'axios'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'


const service = axios.create({
  baseURL: '/mock',  // 配置基础路径
  timeout: 20000,  //和超时限制
});


//请求拦截器
//请求拦截器内部一般不会处理错误的信息
service.interceptors.request.use(config => {
  //config是发送请求的配置对象,必须处理完返回这个配置对象
  //开启我们的进度条
  NProgress.start()
  return config
});
// 响应拦截器
service.interceptors.response.use(
  response => {
    //停止进度条
    NProgress.done()
    //返回响应的时候,直接返回响应的data
    return response.data
  },
  error => {

    NProgress.done()

    alert('请求出错' + error.message || '未知错误')
    //以后不允许用户继续处理: 中断promise链
    return new Promise(() => {}) //返回pending状态的promise 中断
    //以后它允许用户继续对错误进行处理
    // return Promise.reject(error)
  }
);


export default service

 

4.在api---index.js中,使用mock的接口去请求 banner数据 

引入二次封装的ajax;    import mockAjax from '@/ajax/mockAjax'

// 使用mock的接口去请求 banner数据   get 请求     /banner
export const reqBannerList = () => mockAjax.get('/banner')
export const reqFloorList = () => mockAjax.get('/floor')

5.在入口文件main.js中导入mock接口函数

//这个是为了测试接口请求函数  后期也会使用这样的方式去使用
import * as API from '@/api'
//这个是为了测试接口请求函数  后期也会使用这样的方式去使用
import * as API from '@/api'
// console.log(API)
// API.reqBannerList()
// API.reqFloorList()

 

6.在store---home.js,中,将mock请求的数据保存在vuex中

home.js内容

import {reqCategoryList,reqBannerList,reqFloorList} from '@/api'

const state = {
  categoryList : [],
  bannerList:[],
  floorList:[]
}
const mutations = {
  //直接修改数据
  RECEIVECATEGORYLIST(state,categoryList){
    state.categoryList = categoryList
  },
  RECEIVEBANNERLIST(state,bannerList){
    state.bannerList = bannerList
  },
  RECEIVEFLOORLIST(state,floorList){
    state.floorList = floorList
  }
}

const actions = {
  //异步请求数据
  //async 和 await的用法
  async getCategoryList({commit}){
    const result = await reqCategoryList()
    if(result.code === 200){
      commit('RECEIVECATEGORYLIST',result.data)
    }
  },
  async getBannerList({commit}){
    const result = await reqBannerList()
    if(result.code === 200){
      commit('RECEIVEBANNERLIST',result.data)
    }
  },
  async getFloorList({commit}){
    const result = await reqFloorList()
    if(result.code === 200){
      commit('RECEIVEFLOORLIST',result.data)
    }
  },
  
}

const getters = {
  bannerList(state){
    return state.bannerList
  }
}

export default {
  state,
  mutations,
  actions,
  getters
}

 

vuex的数据

 

 

 
7.在listContainer组件,index.vue中,关联到vuex,     this.$store.dispatch("getBannerList");
 
  mounted() {
    this.getBannerList();
}
 
 methods: {
    getBannerList() {
      this.$store.dispatch("getBannerList");
    }
  },
 
获取vuex的数据
import { mapGetters } from "vuex";
 
 computed: {
    // 总的store 内部的state比较特殊  state总的内部会有home,数据是放在home对象内部
    // 其它的getters  mutations  actions 都没有
    // ...mapState({
    //   bannerList : state => state.home.bannerList
    // })
    ...mapGetters(["bannerList"])
  },

在html模板中填充数据

<div class="swiper-wrapper">
            <div class="swiper-slide" v-for="(banner, index) in bannerList" :key="banner.id">
              <img :src="banner.imgUrl" />
            </div>
            
          </div>

此时mock模拟接口的图片需要放在public文件夹中,图片才会显示

 

 
8.home组件index.vue中,关联到vuex,     this.$store.dispatch('getFloorList')
获取数据
import { mapState } from 'vuex'
 computed:{
    ...mapState({
      floorList: state => state.home.floorList
    })
  }

组件数据

 

 

 

注:此时数据在父组件home中,需要将数据传给子组件floor组件中,父子通信,属性传递

<template>
  <div>
    <TypeNav></TypeNav>
    <ListContainer></ListContainer>
    <Recommend></Recommend>
    <Rank></Rank>
    <Like></Like>
    <Floor v-for="(floor, index) in floorList" :key="floor.id" :floor="floor"></Floor>
    <Brand></Brand>
  </div>
</template>

 

子组件floor接收数据   props:['floor'],

html模板填充数据

<div class="blockgary">
              <ul class="jd-list">
                <li v-for="(keyword, index) in floor.keywords" :key="index">{{keyword}}</li>
              </ul>
              <img :src="floor.imgUrl" />
            </div>
 <div class="split">
              <span class="floor-x-line"></span>
              <div class="floor-conver-pit">
                <img :src="floor.recommendList[0]" />
              </div>
              <div class="floor-conver-pit">
                <img :src="floor.recommendList[1]" />
              </div>
            </div>

 

 

 二, 轮播图swiper基本使用及动态数据

1.安装5版本的swiper,  npm  i swiper@5  -S     目前最新是6,不稳定

2.在listContainer组件中,引入swiper, 

//swiper引入js和css
// import Swiper from "swiper";
// import "swiper/css/swiper.min.css";
 
轮播图html模板
 <!-- <div class="swiper-container" ref="banner">
          <div class="swiper-wrapper">
            <div class="swiper-slide" v-for="(banner, index) in bannerList" :key="banner.id">
              <img :src="banner.imgUrl" />
            </div>
            
          </div>
          <div class="swiper-pagination"></div>

          <div class="swiper-button-prev"></div>
          <div class="swiper-button-next"></div>
        </div> -->

 

 

3. 实例化swiper对象

  mounted() {
    this.getBannerList();
    //为什么Swiper在实例的时候放在mounted当中 静态数据是可以的
    //动态数据就不行
    // 静态数据一上来就加载完成了,我们页面的结构也就形成了,然后创建swiper 理所当然就可以
    //动态数据 是我们异步请求的,mounted里面发请求完之后 立即实例化swiper,此时请求的数据不一定回来
    //而我们的页面结构是依赖动态的数据进行创建的
    // new Swiper(this.$refs.banner, {
    //   // direction: "vertical", // 垂直切换选项,默认是水平切换
    //   // loop: true, // 循环模式选项

    //   // 如果需要分页器
    //   pagination: {
    //     el: ".swiper-pagination"
    //   },

    //   // 如果需要前进后退按钮
    //   navigation: {
    //     nextEl: ".swiper-button-next",
    //     prevEl: ".swiper-button-prev"
    //   }

    //   // 如果需要滚动条
    //   // scrollbar: {
    //   //   el: ".swiper-scrollbar"
    //   // }
    // });
  },

注:此时swiper没有效果,因为页面还没有渲染成型,更深的说,this.getBannerList();发送ajax,是异步的,数据还没有请求过来,页面就还未渲染

 
处理方法,解决请求动态数据,有swiper轮播图的效果,
此时需要去监视请求的数据bannerList,如果请求的数据过来了,才可以实例化swiper,此时才会去渲染页面
 
4.处理方法,监视bannerList
 // watch: {
  //   bannerList: {
  //     handler() {
  //       //Vue.nextTick或者vm.$nextTick是一样的功能
  //       //在最近的一次dom更新之后执行nextTick里面传的回调函数
  //       this.$nextTick(() => {
  //         new Swiper(this.$refs.banner, {
  //           // direction: "vertical", // 垂直切换选项
  //           // autoplay:true,//等同于以下设置
  //           loop: true, // 循环模式选项

  //           // 如果需要分页器
  //           pagination: {
  //             el: ".swiper-pagination"
  //           },

  //           // 如果需要前进后退按钮
  //           navigation: {
  //             nextEl: ".swiper-button-next",
  //             prevEl: ".swiper-button-prev"
  //           }

  //           // 如果需要滚动条
  //           // scrollbar: {
  //           //   el: ".swiper-scrollbar"
  //           // }
  //         });
  //       });
  //     },
  //     immediate:true //立即执行,在最近dom更新之前就会执行
  //   },

  // }

 

注:此时swiper轮播图还是没有数据,因为,数据跟新了,但是此时有v-for, 页面还未渲染,此时需要引入vm.$nextTick

在最近的一次dom更新之后执行nextTick里面传的回调函数,这时,swiper轮播图才有效果

 

 floor组件依次引入swiper,进行轮播图切换

抽离公共的swiper组件,注册为全局组件,将数据传入swiper组件