电商项目相关笔记

一、路由传递参数相关面试题

1. 路由传递参数(对象写法)path是否可以结合params参数一起使用?

答:不能,路由跳转传参时,对象的写法命名路由可以是name或path形式,但需要传递params参数时,不能以path这种写法。

2. 如何指定params参数可传可不传?

答:配置路由的时候,占位了params参数(path: '/search/:keyword',)但是路由跳转的时候却不传递,路径会出现问题。解决方法:配置路由时params参数占位后面加了问号path: '/search/:keyword?',代表这个params参数可传可不传。

3. params参数可以传递也可以不传递,但如果传递的是空串,如何解决?

params: {

keyword: "",

},

路径会出现问题

答:使用undefined解决,params参数可以传递,也可以不传递(空的字符串)

      this.$router.push({
        name: "search",
        params: {
          keyword: "" || undefined,
        },
        query: {
          k: this.keyword.toUpperCase(),
        },
      });

4. 路由组件能不能传递props数据?(很少使用)

答:可以,有3种写法

a. 布尔值写法:配置路由时加上 props: true, 这种写法只能传递params参数

b. 对象写法:配置路由时加上 props: { a: 1, b: 2 }, 额外给路由组件传递一些props

c. 函数写法:配置路由时加上如下代码,可以把params参数、query参数,通过props传递给路由组件

    props: ($route) => {
      return {
        keyword: $route.params.keyword,
        k: $route.query.k
      }
    }

*一般路由传参直接通过 $route.params.keyword 形式就可以获取,而不需要通过props传递

二、问题解决

1. 编程式路由跳转到当前路由(参数不变),多次执行会抛出NavigationDuplicated的警告错误?

路由跳转有两种形式:声明式导航(router-link)、编程式导航(函数)

声明式导航没有这类问题,因为vue-router底层已经处理好了

为什么编程式导航进行路由跳转时,会有这种警告错误?

最新的vue-router引入了promise

push方法相当于 

function push(){ return new Promise((resolve, reject)=>{}) }

promise需要传递成功或失败的回调,才能捕获异常

如何处理:在调用push时,除了传递往哪跳的参数,还要传递相应的成功的、失败的回调函数,就可以捕获到当前的错误。但这种写法治标不治本

治本:重写push和replace

// 先把VueRouter原型对象的push和replace保存一份
let originPush = VueRouter.prototype.push;
let originReplace = VueRouter.prototype.replace;
// 重写push与replace
// 第一个参数:location,告诉原来的push方法,往哪里跳转,以及传递哪些参数
// 第二个参数:成功的回调
// 第二个参数:失败的回调
VueRouter.prototype.push = function (location, resolve, reject) {
  if (resolve && reject) {
    originPush.call(this, location, resolve, reject)
  } else {
    originPush.call(this, location, () => { }, () => { })
  }
};
VueRouter.prototype.replace = function (location, resolve, reject) {
  if (resolve && reject) {
    originReplace.call(this, location, resolve, reject)
  } else {
    originReplace.call(this, location, () => { }, () => { })
  }
}

call和apply

相同点:都可以调用函数一次,都可以篡改函数上下文一次

不同的:call传递参数用逗号隔开,apply用数组传递参数

三、跨域问题可以通过代理服务器解决

跨域的解决方案:JSONP、CROS、代理

在vue.config.js文件中配置代理跨域

  // 代理跨域
  devServer: {
    proxy: {
      '/api': {
        target: 'http://gmall-h5-api.atguigu.cn',
        // pathRewrite: { '^/api': '' },  //重写路径,让所有的路径都带/api
      }
    }
  }

前端项目发送请求时如果路径中带有/api,代理服务器就会转发请求,找真实的服务器要数据,返回到前端项目展示

此时axios中的baseURL不需要写服务器ip地址

四、nprogress进度条插件

项目中出现发请求,进度条就会往前跑,当服务器数据返回成功,进度条就会消失

nprogress对象中,start()方法代表进度条开始动,done()方法代表进度条结束

可以在网络请求中引入import nprogress from 'nprogress',并引入样式import 'nprogress/nprogress.css';

在请求拦截器调用开始方法,响应拦截器调用结束方法

进度条颜色可通过样式修改

五、防抖与节流

防抖:前面所有的触发都被取消,最后一次执行在规定时间之后才会触发。即如果连续快速触发,只会执行最后一次。 

节流:第一次触发回调后,在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会再次触发回调,把频繁触发变为少量触发。即每次触发后禁用一段时间。

lodash插件:里面封装了函数的防抖与节流的业务(包含闭包、延迟器的知识)

lodash函数库对外暴露的是一个_函数(类似jQuery暴露$函数)

    // 防抖
    const input = document.querySelector('input');
    input.oninput = _.debounce(function () {
      console.log('发送请求')
    }, 1000);
    // 节流
    const span = document.querySelector('span');
    const btn = document.querySelector('button');
    let count = 0;
    btn.onclick = _.throttle(function () {
      count++;
      span.innerHTML = count;
    }, 1000);

throttle的回调函数不要用箭头函数,可能出现上下文this问题

六、路由跳转

(1)声明式导航:router-link (2)编程式导航:push/replace

使用router-link出现卡顿现象:因为router-link是一个组件,当服务器数据返回后,如果循环出大量的router-link组件(组件要创建组件实例,还要将虚拟DOM转化为真实DOM),在创建组件实例时,一瞬间创建过多很耗内存,因此出现卡顿。

最好的解决方案:编程式导航+事件委派(把所有子节点的事件委派给父节点)-----------案例:三级联动组件 vue-shangpinhui > src > components > TypeNav

七、过渡:<transition> 元素作为单个元素/组件的过渡效果

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

  • 条件渲染 (使用 v-if)
  • 条件展示 (使用 v-show)
  • 动态组件
  • 组件根节点

前提:组件或元素务必要有v-if或v-show指令才可以进行过渡动画

        <!-- 过渡动画 -->
        <transition name="sort">
          <div class="sort" v-show="show">...
          </div>
        </transition>

transition标签不加name属性时,通过.v-enter、.v-enter-to、.v-enter-ative等来写样式;

如果加了name属性,如name='fade',则通过 .fade-enter、.fade-leave-to等写样式。

name 属性是用来自定义过渡类名前缀,因为不写name如果有多个动画就分不清了。

<div id="example-1">
  <button @click="show = !show">
    Toggle render
  </button>
  <transition name="slide-fade">
    <p v-if="show">hello</p>
  </transition>
</div>
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.slide-fade-enter-active {
  transition: all .3s ease;
}
.slide-fade-leave-active {
  transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active for below version 2.1.8 */ {
  transform: translateX(10px);
  opacity: 0;
}

八、mock数据

需要用到mockjs插件

mock数据不会和服务器进行任何通信,请求会被浏览器拦截

使用步骤:

1. 在项目的src文件夹中创建一个mock文件夹

2. 准备JSON数据

3. 把mock数据需要的图片放置在public文件夹中(public文件夹在打包时会把相应的资源原封不动地打包到dist文件夹中)

4. 开始mock虚拟的数据,通过mockjs模块实现:创建mockServe.js,通过mockjs插件实现模拟数据

// 先引入mockjs模块
import Mock from 'mockjs';
// 把JSON数据格式引入进来
import banner from './banner.json';
import floor from './floor.json';

// mock数据:Mock对象上的mock方法
// 第一个参数:请求的地址
// 第二个参数:请求的数据
Mock.mock('/mock/banner', { code: 200, data: banner });//模拟轮播图数据
Mock.mock('/mock/floor', { code: 200, data: floor });

5. 把mockServe.js在入口文件中引入(至少执行一次,才能模拟数据)

// 引入mockServe.js-------用于mock数据
// 这个模块只需要引进来执行一次就可以,不需要import A from B,所以这个模块根本不用对外暴露
import '@/mock/mockServe';

因为只用执行,不调用里面的东西,也就不用获取这个模块,所以mockServer.js不用暴露,import的文件不论你导不导出都会全部编译一次,引入了就相当于执行了里面的代码。

*webpack默认对外暴露的有:图片、JSON数据格式

九、swiper插件的基本使用

1. 引包(相应的css、js)

2. 页面中的结构务必要有

3. new Swiper实例(给轮播图添加动态效果)

十、侦听器watch

监听组件实例身上的属性的属性值变化

Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

十一、nextTick

vm.$nextTick( [callback] )

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

回调的 this 自动绑定到调用它的实例上

该方法可以保证页面中的结构一定是有的,且经常和很多插件一起使用(很多插件需要DOM已经存在)

十二、本地存储

一些简单的数据skuNum通过query形式给路由组件传递过去,产品信息的数据skuInfo(较复杂),通过会话存储(不持久化,会话结束数据再消失)

浏览器存储功能:HTML5新增,本地存储、会话存储

本地存储localStorage:持久化的 ------ 5M

会话存储sessionStorage:并非持久 ------ 会话结束,数据就消失

本地存储、会话存储一般存储的是字符串,不能存对象,要先把对象转化成JSON字符串

十三、uuid 临时游客身份

发送请求时,获取不到购物车的数据,因为服务器不知道你是谁

解决方法:uuid 临时游客身份(也可以用nanoid)

1. 在utils的uuid_token.js文件中写一个生成uuid的函数

import { v4 as uuidv4 } from 'uuid';
// 这个函数要生成一个随机字符串,且每次执行不能发生变化,游客身份持久存储(localStorage)
export const getUUID = () => {
  // 先从本地存储获取uuid(检查是否已经有了)
  let uuid_token = localStorage.getItem('UUIDTOKEN');
  // 如果没有就生成游客临时身份,本地存储存一次
  if (!uuid_token) {
    uuid_token = uuidv4();
    localStorage.setItem('UUIDTOKEN', uuid_token);
  }
  return uuid_token;
}

2. 在vuex仓库的detail模块中使用

// 封装游客身份的模块uuid:生成一个随机字符串(生成一次不能再变了)
import { getUUID } from '@/utils/uuid_token'

const state = {
  goodInfo: {},
  // 游客的临时身份
  uuid_token: getUUID(),
};

3. 在api请求文件的请求拦截器中,给请求头添加userTempId字段

// 1.请求拦截器:在发送请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情
requests.interceptors.request.use(config => {
  // config是配置对象,里面有一个属性很重要,即headers请求头
  if (store.state.detail.uuid_token) {
    // 给请求头添加一个字段(userTempId),且该字段应该已经和后台商量好了才能加
    config.headers.userTempId = store.state.detail.uuid_token;
  };
  // 进度条开始动
  nprogress.start();
  return config;
})

发送请求时就在请求头中带了这个参数,服务器就可以确定是谁把商品加入购物车的,购物车组件发送请求时就能获取到购物车的数据

十四、assets文件夹的作用

vue项目的assets文件夹用于放置全部组件共用的静态资源

十五、token

用户的唯一标识

登录业务:

1. 注册---通过数据库存储用户信息(名字、密码)

2. 登录---登录成功的时候,后台为了区分你这个用户是谁,服务器下发token(令牌,唯一标识符)

一般登录成功,服务器会下发token,前台持久化存储token(带着token找服务器要用户信息的数据进行展示)

注意:vuex仓库存储数据不是持久化的,一刷新就没了

十六、导航守卫

参数:

to: 要跳转到的路由的信息

from: 从哪个路由来

next: 放行函数  

next();直接放行  

next('/login');放行到指定路由  

next(false);回到from的位置,即停留在当前位置(history模式下会导致路由清空router-view空白)

十七、注意事项

不能在生命周期函数上使用 async

十八、组件库

React:antd【PC端】,antd-mobile【移动端】

Vue:ElementUI【PC端】,vant【移动端】

十九、图片懒加载

vue-lazyload

vue-lazyload - npmhttps://www.npmjs.com/package/vue-lazyload

二十、表单验证

vee-validate

GitHub - logaretm/vee-validate: ✅ Form Validation for Vue.jshttps://github.com/logaretm/vee-validate

二十一、Linux 常用指令

 cd 跳转目录

ls 查看

mkdir 创建目录

pwd 查看绝对路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值