电商平台项目----三级联动

49 阅读1分钟

电商平台项目----三级联动

目录

[TOC]

三级联动

由于三级联动在Home Search Detail 把三级联动注册为去全局组件

只需要注册一次,就可以在项目任意地方使用

第一个参数为全局组件的名字,第二个为那个组件

Vue.component(TypeNav.name, TypeNav)

TypeNav 为全局组件不需要引入

网络请求

axios的二次封装

放置在api文件夹中 接口统一处理 挂载到原型Vue.prototype.$api = axios

请求拦截器requests.interceptors.request.use:可以在发请求之前处理一些业务

响应拦截器 requests.interceptors.response.use:当服务器返回数据之后处理业务

baseURL: '/api' 基础路径,发送请求的时候路径中会出现api

timeout: '5000', 请求超时时间 5s

// 对axios二次封装
import axios from 'axios'
 
 
// 利用axios对象方法的created,创建一个axios实例
const requests = axios.create({
    //配置对象
    // 基础路径,发送请求的时候路径中会出现api
    baseURL: '/api',
    //请求超时时间 5s
    timeout: '5000',
})
//请求拦截器
requests.interceptors.request.use((config) => {
    // config配置对象 header请求头
    return config
})
//响应拦截器
requests.interceptors.response.use((res) => {
    //成功的回调函数
    return res.data
}, (error) => {
    //响应失败的回调函数
    return Promise.reject(new Error('false'))
})
export default requests

跨域问题

协议 域名 端口号 不一致称为跨域

jsonp ,cros, 代理

浏览器跟服务器之间才有跨域问题,服务器跟服务器之间没有

在vue.config.js中配置webpack配置项

  //代理跨域
  devServer: {
    proxy: {
      "/api": {
        target: "http://gmall-h5-api.atguigu.cn",
        pathRewrite: { "^/api": "" }
      }
    }
  }

模块化导入导出

export default{} 导出对象 导入使用 import axios from 'axios'

export const a 导出变量  导入某个变量解构赋值

export const a 导出变量  import * as axios from 'axios' 导入全部变量

vuex状态管理库

vuex是官方提供的插件 状态管理库, 集中式管理项目中的组件共用数据 多个组件依赖同一个值

new Vuex.Store 对象暴露一个store类的一个实例

Vue.use(Vuex) 需要使用插件

state   仓库存储数据的地方

vuex  设置值 const state = {count: 1};

1辅助函数映射为组件的计算属性
  数组形式
  import { mapState } from "vuex";
  computed: {...mapState(["count"])},
  对象形式 可以指定键
  computed: { ...mapState({ n: "count"}),
  函数形式
  computed: {
    ...mapState({
      //右侧需要的是一个函数,当使用这个计算属性的时候,右侧函数会立即执行一次
      //注入一个state
      CategoryList:state=>state.home.CategoryList
    }),
2计算属性
  computed: {
    count() {
      return this.$store.state.count;
    },
  },
3具体的数据名称小胡子语法

{{this.$store.state.count}}

mutations mutations修改state中的唯一手段 commit执行

// state 仓库  payload载荷
    add(state, payload) {
        state.count++
        state.count += payload
      }
1.直接执行

this.$store.commit("add", 1);

2辅助函数(也可以是对象自定义事件句柄)
 
import { mapMutations } from "vuex";
  methods: {...mapMutations(["add"])},
  <button @click="add(1)">点我加一</button>

actions  可以手写自己的业务处理异步 dispatch派发

// content vuex上下文 payload 载荷
    addSync(content, payload) {
        content.commit('add', payload)
    }
1.直接派发

this.$store.dispatch("add", 1);

2辅助函数(也可以是对象自定义事件句柄)
import { mapActions } from "vuex";
methods: {...mapActions(["addSync"])},
<button @click="addSync(1)">点我加一</button>

getters 计算属性

vuex
    showNum(state) {
        return state.arr.filter(item => {
            return item > 10
        })
    }
1.直接读取

{{ this.$store.getters.showNum }}

2.计算属性
  computed: {
    arr() {
      return this.$store.getters.showNum;
    },
  },
3辅助函数映射为组件的计算属性
  数组形式
 
  import { mapGetters } from "vuex";
 
  computed: {...mapGetters(["arr"])},
 
  对象形式 可以指定键
 
  computed: { ...mapGetters({ a: "arr"}),

modules 模块化开发

// search 组件的小仓库
const state = {}
const mutations = {}
const actions = {}
const getters = {}
export default {
    state,
    mutations,
    actions,
    getters
}
vuex
import Vue from 'vue'
import Vuex from 'vuex'
import home from './home'
import search from './search'
//需要使用插件
Vue.use(Vuex)
 
 
// 对象暴露一个store类的一个实例
export default new Vuex.Store({
    modules: {
        home,
        search
    }
})

动态添加样式或者类名

动态添加背景颜色

第一种css :hover 伪类选择器 选择器用于选择鼠标指针浮动在上面的元素。

   .item:hover {
          background: blue;
    }

第二种:js

<h3 @mouseenter="changeIndex(index)" @mouseleave="leaveIndex"> </h3>
    动态绑定类名 移入元素索引==响应式数据添加样式
   :class="{ cur: currentIndex == index }"
     data() {
    return {
      currentIndex: -1,
    };
  },
    methods: {
    //鼠标移入改变响应式数据
    changeIndex(index) {
      //index鼠标移入的索引值
      this.currentIndex = index;
    },
    //鼠标移除的事件
    leaveIndex() {
      this.currentIndex = -1;
    },
  },

二三级分类的显示和隐藏、

css display: none; 鼠标滑过display:block

js  :style="{ display: currentIndex == index ? 'block' : 'none' }"

函数的防抖和节流

//index鼠标移入的索引值

/正确情况下每一个都会触发鼠标移入事件

// 如果很快只触发部分,由于用户操作行为过快,导致浏览器解析不过来出现卡顿

防抖:前面的所有的触发都取消,最后执行一次 在规定的时间之后才会触发,多次点击只会执行一次

节流:在规定的时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发

防抖:用户操作很频繁但 只执行一次    节流 用户操作很频繁 降低触发频率

lodash插件里面封装了函数防抖与节流【闭包+延迟器】

lodash函数库对外暴露了函数

防抖
input.oninput=_.debounce(function(){
console.log('ajax请求')
},1000)
节流
button.onclick=_.throttle(function(){
  //:节流目前这个回调函数5s执行一次,给浏览器解析时间
  count++
},5000)

项目应用

// 全部引入
import _ from "lodash";
    changeIndex: _.throttle(function (index) {
      console.log(index);
      this.currentIndex = index;
    }, 50),

自定义属性

router-link为vue内部组件如果循环组件会出现延迟

三级联动 最好的解决方案:编程时导航+事件委托

通过自定义属性 :data-categoryName 区分a标签

取自定义属性值:event.target.dataset.自定义属性 对象、浏览器自动把自定义属性转为小写

event事件对象

  • 1.自定义属性 :data-自定义属性
  • 2.获取自定义属性值:event.target.dataset.自定义属性
   goSearch(event) {
      // event事件对象
      //最好的解决方案:编程时导航+事件委托
      // 通过自定义属性 :data-categoryName 区分a标签
      //获取自定义属性值:event.target.dataset.自定义属性 对象、浏览器自动把自定义属性转为小写
      let element = event.target;
      let { categoryname, category1id, category2id, category3id } =
        element.dataset;
      //如果有自定义属性 categoryname 一定是a标签
      if (categoryname) {
        let location = {
          name: "Search",
        };
        let query = { categoryName: categoryname };
        // 一级二级三级分类的a标签
        if (category1id) {
          query.category1Id = category1id;
        } else if (category2id) {
          query.category2Id = category2id;
        } else {
          query.category3Id = category3id;
        }
        //整理完整参数
        location.query = query;
        // 路由跳转
        this.$router.push(location);
      }
    },

过度动画

前提:组件,元素比需要有v-if|v-show 指令才可以进行过度动画

使用内置组件   要有name

通过样式添加动画

  • .sort-enter     //开始状态(进入)
  • .sort-enter-to      //结束状态(移除)
  • .sort-enter-active {transition: all 0.5s linear; } //定义动画的时间 速率

路由参数合并

如果既有query参数,右有paramis参数要进行合并避免丢失

    goSearch() {
      if (this.$route.query) {
        let location = {
          name: "Search",
          params: { keyWord: this.keyWord },
        };
        location.query = this.$route.query;
        this.$router.push(location);
      }
    },