尚品汇项目

1.vue文件目录分析

node_modules文件夹:项目依赖文件夹。
public文件夹:一般放置一些静态资源(如:图片),webpack打包时会原封不动的打包到dist文件夹中。
src文件夹(源代码文件夹):

  • assets文件夹:一般也是放置静态资源,(如:放置多个组件共用的静态资源),webpack在打包时,会把这些静态资源当成时一个模块,打包在js文件里面。
  • components文件夹:一般放置的是非路由组件(全局组件)。
  • App.vue:唯一的根组件,Vue当中的组件(.vue)。
  • main.js:程序入口文件,也是整个程序中最先执行的文件。

babel.config.js:配置文件(babel相关)。
package.json文件:记录项目的详细信息,如项目中有哪些依赖、如何运行、名称等。
package-lock.json:缓存性文件,记录了当前项目所依赖的模块版本。

2.项目的配置

2.1开发环境打包完成,浏览器自动打开
//package.json中
"scripts": {
    "serve": "vue-cli-service serve --open",
    "build": "vue-cli-service build"
  }
2.2 eslint校验功能关闭
//在根目录下,创建一个 vue.config.js 文件
module.exports = {
    lintOnSave:false
}
2.3 src文件夹简写方法,配置别名
//在根目录下,创建jsconfig.json 配置别名@,用@/ 替代src/ ,在文件数量多,嵌套层次多的时候尤为方便
//exclude表示的是不可使用该别名的文件
{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@/*":["src/*"]
    }
  },
  "exclude": ["node_module","dist"]
}

3.组件的使用

3.1 非路由组件的使用步骤
  • 在components文件夹中创建组件
  • 在其他组件中引入并且注册组件
  • 已标签的形式使用
3.2 路由组件的使用
  • 在views/pages文件夹中创建路由组件
  • 在router文件夹中index.js中配置路由
3.3 路由组件和非路由组件区别:
  • 非路由组件放在components中,路由组件放在pages或views中
  • 非路由组件通过标签使用,路由组件通过路由使用
  • 在main.js注册完路由,所有的路由和非路由组件身上都会拥有$router $route属性
  • $router:是vueRouter的实例对象,是一个全局的对象,他包含了所有的路由,包含了许多关键的对象和属性
  • $route: 每一个路由都会有一个 $route对象,是一个局部的对象,可以获取对应的name,path,params,query等
3.4 Footer组件的显示与隐藏
  • 可以使用v-if 或v-show,因为v-if频繁操作Dom消耗性能,v-show只是对元素的显示或隐藏这里使用v-show
  • 给路由配置元信息meta,在元信息中定义show属性,值为布尔值
	{
        path: '/home',
        component: Home,
        meta: {
            show: true
        }
    },
    {
        path: '/login',
        component: Login,
        meta: {
            show: false
        }
    }
  • 将show的值赋给v-show,从而按需展示隐藏Footer组件
  • 路由配置对象的key不能瞎写

4.路由传参

4.1 路由跳转的方式
  • 声明式导航
//必须有to,可以把router-link理解为一个a标签,它 也可以加class修饰
<router-link to="/"></router-link>
  • 编程式导航
//编程式导航除了路由跳转,在跳转之前还可以处理一些业务逻辑
this.$router.push('/')
4.2 路由传参
  • 方法一:字符串或模板字符串传参
  • 方法二:对象形式传参
  • 注意:
    query参数:不属于路径当中的一部分,类似于get请求,地址栏表现为 /search?k1=v1&k2=v2
    query参数对应的路由信息 path: “/search”
    params参数:属于路径当中的一部分,需要注意,在配置路由的时候,需要占位 ,地址栏表现为 /search/v1/v2
    params参数对应的路由信息要修改为path: “/search/:keyword” 这里的/:keyword就是一个params参数的占位符
  • 路由传递参数(对象写法),如果我们传参中使用了params,只能使用name,不能使用path,如果只是使用query传参,可以使用path,所以,路由需要配置name字段,传参的语法为
this.$router.push({name:'search',params:{},query:{} })
  • 指定params参数可传可不传
//在占位符后加 ?即可
path('/search/:keyWord?')
  • params参数可传可不传,但如果传递的是空串,跳转地址信息则缺少/search,如何解决呢?
this.$router.push({name:'search',params:{keyWord:''||undefined})
  • 路由组件能不能传递props数据?
    答案是可以的:
    props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给组件;
    props值为对象,该对象中所有的key-value的组合最终都会通过props传给组件;
    props值为函数,该函数返回的对象中每一组key-value都会通过props传给组件

5.多次push相同路由报错问题

//在router的index.js文件中添加如下代码
import Vue from 'vue'
import VueRouter from 'vue-router'

//解决重复push相同路由报错问题
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
    return originalPush.call(this, location).catch(err => err)
}

6. axios二次封装

6.1 为什么需要二次封装axios
//配置请求拦截器、响应拦截器,可以在发送请求之前处理一些业务、响应拦截器可以在数据返回之后处理一些事情
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
  });
6.2 自定义axios实例
//可以使用自定义配置新建一个实例
const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});

7.请求接口统一封装

7.1 在api文件夹中创建index.js文件,用于封装所有请求,将每个请求封装为一个函数并暴露出去,组件只需要调用相应函数即可
import requests from "@/api/request";
//首页三级分类接口
export const reqCateGoryList = () => {
    return  requests({
        url: '/product/getBaseCategoryList',
        method: 'GET'
    })
}
import {reqCateGoryList} from './api'
//发起请求
reqCateGoryList();
7.2 前端通过代理解决跨域问题
//在vue.config.js中配置
module.exports = {
    //关闭eslint
    lintOnSave: false,
    devServer: {
        // true 则热更新,false 则手动刷新,默认值为 true
        inline: false,
        // development server port 8000
        port: 8001,
        //代理服务器解决跨域
        proxy: {
            //会把请求路径中的/api换为后面的代理服务器
            '/api': {
                //提供数据的服务器地址
                target: 'http://39.98.123.211',

            }
        },
    }
}

8.vuex的使用

8.1 vuex的基本使用
//安装并引入vuex,根目录创建store文件夹,创建index.js文件
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

//创建store仓库并暴露出去
export default new Vuex.Store({
//state包含组件的状态,是数据源
//注意:vuex中的数据不是永久的,页面刷新后,数据会被重置
    state:{
     count: 0
     },
     //更改store中状态的唯一方法是提交mutation,在组件中通过method提交mutation
    mutations:{
	 increment(state) {
            return state.count++
     }
	},   
})
//在main.js中引入上述文件,并在vue实例中注册store
import store from './store'
new Vue({
  render: h => h(App),
  //注册路由,此时组件中都会拥有$router $route属性
  router,
  //注册store,此时组件中都会拥有$store
  store
}).$mount('#app')
8.2 在 Vue 组件中获得 Vuex 状态
//方法一 ,在组件中通过computed返回state中数据
computed: {
    count() {
      //state数据是响应式的,通过计算属性将获取的数据返回即可
      return this.$store.state.count;
    },
},

//方法二 ,使用mapState辅助函数,当一个组件需要多个状态都声明为计算属性会比较冗余,可以使用辅助函数生成计算属性
  computed: mapState(['count']),
8.3 更改state中的状态
  • 提交mutation是变更state状态的唯一途径,state中的数据不可以直接更改,需要通过提交mutation来更改状态
  • commit mutation的行为在组件的methods节点中触发
  • 好处:可以追踪数据的变更,方便后期的维护
  • 实例:
//在mutations中定义更改数据的方法
    mutations:{
    //除了传入state数据源还可以传入额外的参数
	 increment(state) {
            return state.count++
     }
	}
	
//在组件中提交变更
//方法一 , this.$store.commit
methods: {
    addCount() {
      //在方法中通过提交一个mutation的方式提交变更
      this.$store.commit('increment');
    },
  }
  
//方法二 , 使用mapMutations辅助函数将methods映射为 store.commit 调用,在组件中直接使用increment作为事件处理函数即可
 methods: {
    ...mapMutations(['increment']),
  }
8.4 异步操作更改state状态
  • action用于处理异步任务
  • mutation只能处理同步任务,异步任务在actions中定义,action不能直接更改state,如果需要异步操作更改state,需要在action中提交mutation
  • 如何在组件中触发异步变更呢?
actions: {
        //action不能直接修改state,需要通过提交mutation变更state
        incrementAsync(context) {
            setTimeout(() => {
                context.commit('increment')
            },1000)
        }
    }
    
//方法一 , this.$store.dispatch
 methods: {
    addCountAsync() {
    //在组件中触发异步函数
      this.$store.dispatch('incrementAsync');
    },
  },
  
//方法二 ,使用mapActions
 methods: {
    ...mapActions(['incrementAsync']),
  },
8.5 模块式开发——modules
  • 组件中所有的状态都集中到同一个仓库中,会非常臃肿,所以可以将store分割成模块(小仓库),每个module都会有自己的state、mutation、action、getter
  • 步骤:
//在store中创建小仓库
import { getBaseCategoryList } from '@/api/index.js'

export default {
    state: {
        categoryList: []
    },
    mutations: {
        getCateList(state, categoryList) {
            state.categoryList = categoryList
            console.log(state.categoryList);
        }
    },
    actions: {
        async getCateList(context) {
            const { data: res } = await getBaseCategoryList()
            console.log(res);
            if (res.code !== 200) {
                return
            }
            context.commit('getCateList', res.data)
        }
    }
}

//在大仓库中导入小仓库
import home from '@/store/home/index.js'
import search from './search';

export default new Vuex.Store({
    modules: {
        home,
        search
    },
});

//在组件中获取状态
this.$store.state.home.categoryList;

9.防抖动和节流

9.1 防抖动
  1. 安装并引入lodash
//安装
npm i -S lodash
//引入
import _ from 'lodash'
//防抖,前面所有的触发都会被取消,只会执行最后一次触发,到达规定延迟时间后,调用回调函数,返回新的 debounced(防抖动)函数
let debounced = _.debounce(function(){},1000)
9.2 节流
  1. 在规定的间隔时间内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁的触发变为少量的触发
//表示在1秒内只触发一次回调
_.throttle(function(){},1000)

10.mockjs使用步骤(如果想要模拟数据,需要用到插件mockjs)

  1. 在项目src文件夹下创建mock文件夹;
  2. 准备JSON数据,在mock文件夹中创建相应的JSON文件——注意格式,不要留空格;
  3. 把mock需要的图片放到public文件夹下(public文件夹在项目打包时会原封不动把资源打包到dist中);
  4. 在mock文件夹下新建mockServe.js文件,使用mockjs的mock方法实现模拟数据
import Mock from 'mockjs';
import banners from './banners.json';
import floors from './floors.json';
//mock方法第一个参数是路径,第二个参数是假数据
Mock.mock('/mock/banners', banners);
Mock.mock('/mock/floors', floors);
  1. 在入口文件main.js中引入mockServe.js

11.组件间通信

//父->子 (props)
	//子组件
export default {
  name: 'Floor',
  props: ['floorList']
};
	//父组件 绑定floorList属性并传值
<Floor :floorList="item"></Floor>
//子->父 ($emit)
	//子组件
 methods: {
    sendTrademark(trademark) {
      this.$emit('trademarkInfo', trademark);
    },
  }
  	//父组件 绑定自定义事件
  <SearchSelector @trademarkInfo="trademark"></SearchSelector>
   
  methods: {
    trademark(trademark) {
      this.searchParams.trademark = `${trademark.tmId}:${trademark.tmName}`;
      this.dispatchSearch();
     }
   }
//非父子组件之间 (evenBus)
//先在main.js中创建bus
new Vue({
    router,
    store,
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this
    }
}).$mount('#app')

	//A组件
 removeKeyword() {
      this.$bus.$emit('clear');
  }

	//B组件
mounted() {
    this.$bus.$on('clear', () => {
      this.iptValue = '';
    });
  }

12.数组的一些方法 let arr =[‘1’]

12.1 push()和pop()
  • push(): 可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。 语法:const count = arr.push('2','3'),返回 count=3,此时arr=['1','2','3']
  • pop():数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项,如果数组为空则返回undefined。语法:const remove = arr.pop(),返回remove=3,此时arr=['1','2']
  • 注意:pop()不需要参数,默认移除数组最后一项。
12.2 shift() 和 unshift()
  • shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
  • unshift:将参数添加到原数组开头,并返回数组的长度 。
  • 注意,同push,pop用法相同,一个针对末尾一个针对开头的区别。都是修改了原数组
12.3 concat()
  • concat() :将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。该方法没有修改原数组。
  • 语法:const newArr = arr.concat('4')返回新数组['1', '2', '4'],原数组并未被修改arr=['1', '2']
12.4 slice()
  • slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。
  • 在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。
  • 如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
12.5 splice()
  • splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。
  • 删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。
  • 插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。
  • 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入4和6。
  • splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除任何项,则返回一个空数组。
12.6 indexOf()和 lastIndexOf()
  • indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。
  • lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。
  • 这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回-1。在比较第一个参数与数组中的每一项时,会使用全等操作符。
12.7 过滤 filter()
  • 语法:const a = arr.filter((item)=>return item>1),返回a=['2'],此时arr=['1', '2']
  • 使用filter()会生成一个新的数组,且新数组的变化不会影响原数组。

13.全局守卫

13.1 前置守卫
router.beforeEach((to,from,next)=>{
//to:可以获取你要跳转到的路由信息
//from:可以获取你从哪个路由而来的信息
//next:next()放行  next('/')放行到具体的路由  next(false)驳回
})
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值