/mall

Learn Vue2

Primary LanguageVue

mall

Project setup

npm install

Compiles and hot-reloads for development

npm run serve

Compiles and minifies for production

npm run build

Customize configuration

See Configuration Reference.

记录学习本项目中的问题

  1. VueKey值的作用

在v-if中使用key

由于Vue尽可能高效的渲染元素,通常会复用已有元素而不是从头开始渲染。
因此当我们使用v-if来实现元素切换的时候,如果切换前后含有相同类型的
元素,那么这个元素就会被复用。如果是相同的input元素,那么切换前后
用户的输入不会被清除掉,这样是不符合需求的。因此我们可以通过使用key
来唯一标识一个元素,这个情况下,使用Key的元素不会被复用。

这个时候key的作用是用来标识一个独立的元素。

在v-for中使用key

用v-for更新已渲染过的元素列表时,它默认使用“就地复用”策略。
如果数据项的顺序发生了改变,Vue不会移动DOM元素来匹配数据项
的顺序,而是简单复用此处的每个元素。因此通过为每个列表项提供
一个key值来以便Vue跟踪元素的身份,从而高效的实现复用。

这个时候key的作用是为了高效的更新渲染虚拟DOM。

综上所述:关键是实际开发过程中是否需要复用策略,视情况而定使用key

  1. 开发中使用预定义变量保存一个默认值,方便状态管理

    • tabcontrol的切换:使用currtentIndex保存当前所选tab
      :class="{active: currentIndex === index}
      
  2. 样式设置文字过多显示...

    .show-ellipsis {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  3. 自定义监听事件,不写参数默认传递子组件参数

    在商品显示流行、新款、精选时用到 $emit('tabClick',index)传递子组件信息

  4. Vue的生命周期函数

    在mounted挂载后,才能拿到DOM节点

  5. 组件的事件监听

    若要监听组件上的某些原生事件,可以在事件上加上native修饰符 ---> BackTop应用场景

  6. 组件props参数若为驼峰命名,则使用时需要改为-

  7. 事件总线(非父子组件通信)

    组件之间的层叠关系过多,但又需要监听相互之间的事件,则可以使用事件总线

    // main.js
    vue.prototype.$bus = new Vue()
    
    // 某个组件内的事件
    this.$bus.$emit('eventName')
    
    // 其他组件上监听
    this.$bus.$on('eventName', eventFunction)
    
    // 其他组件上取消监听
    this.$bus.$off('eventName', eventFunction)
  8. 防抖debounce函数

    对于refresh非常频繁的问题,进行防抖操作

    export function debounce(func, delay) { // 防抖函数
    let timer = null
    return function (...args) {
      if (timer) clearTimeout(timer)
      timer = setTimeout(() => {
        func.apply(this, args)
      }, delay)
    }
  9. 如何拿到子组件的offsetTop?

this.$refs.componentName.$el.offsetTop 在tabControl实际应用中记录offsetTop高度值,以便于在Scroll中使用

  1. Better-Scroll中控制管理下,单独控制TabControl吸附

在此场景下很难达到预期的效果,可新增一个TabControl脱离BS的管理

  1. 记录BS中的TabControloffsetTop
  2. BS的滚动距离与offsetTop进行比较
  3. 使用v-show控制其显示与隐藏(距离达到则显示,未到达则隐藏)
  1. 在数据想过于复杂时,可以创建一个类来对数据进行过滤

在DetailBaseInfo中使用该项原则

export class Goods {
constructor(itemInfo, columns, services) {
   this.title = itemInfo.title
   this.desc = itemInfo.desc
   this.newPrice = itemInfo.price
   this.oldPrice = itemInfo.oldPrice
   this.discount = itemInfo.discountDesc
   this.columns = columns
   this.services = services
   this.realPrice = itemInfo.lowNowPrice
  }
}
  1. keep-alive遇见vue-router

    keep-alive中可以记录组件的状态,include或者exclude属性的值必须保持大小写一致

  2. 如果在多个组件中使用相同的钩子函数或者data,可选mixins(混入)

    在Home和Detail组件需要使用防抖操作以及事件总线的监听,使用mixins

    export default {
       //...
       mixins: [mixin]
    }
  3. Detail组件中,点击标题,滚动到对应的主题

  • 在detail中监听标题的点击,获取index
  • 滚动到对应的主题
    • 获取所有子组件的offsetTop
    • 如何获取到正确的offsetTop
      1. created中不可以,DOM还未挂载
      2. mounted中不可以,数据还未获取到
      3. 获取数据的回调中也不行,DOM还没有渲染完毕
      4. $nextTick也不行,图片高度没有被计算在内
      5. 在图片加载完成后,获取的高度才是正确的
  1. 雪碧图的使用

    封装detail组件时,底部按钮使用到雪碧图,可以有效的提高性能 核心点是调整background-position属性

  2. mapGetters 辅助函数

    辅助函数仅仅是将 store 中的 getter 映射到局部计算属性

    import { mapGetters } from 'vuex'
    export default {
    // ...
    computed: {
    // 使用对象展开运算符将 getter 混入 computed 对象中
       ...mapGetters([
           'doneTodosCount',
           'anotherGetter',
           // ...
         ])
       }
    }
  3. 全选和反选

    购物车的全选和反选的思考

    1. 是否显示全选状态(isCheck)?根据cartList.list长度与cartListItemchecked的长度判读
    2. 全选的点击事件
    • cartList.list中的每个元素的checked根据全选的状态,即checkall,统一设定truefalse

      this.cartList.forEach(cartitem => cartitem.checked = !this.checkall)

    • 出现的bug,当点击时状态保持不一致,即非全选状态
    • 思考原因:点击事件不仅仅改变了内部的checked值,同时this.checkall也发生了改变,导致cartlist遍历时数据保持不一致(既有false也有true)
    • 解决方式:定义一个常量const state = !this.checkall,提前记录状态值,防止在遍历时数据的变化
  4. 解决移动端300ms的延迟点击问题

    安装fastclick

  5. 图片的懒加载

    vue-lazyload,仓库地址

  6. px2vw插件->postcss-px-to-viewport

    主要配置postcss.config.js 仓库地址

  7. Vue插件的编写

    用于封装Toast组件,使得在全局状态下可直接使用$toast

      import Toast from './Toast'
      const obj = {}
    
      obj.install = (Vue) => {
      console.log('toast install')
      // 1. 创建组件构造器并实例化
      const toastPlugin = Vue.extend(Toast)
      // 2. new的方式,根据组件构造器,可以创建一个组件对象
      const toast = new toastPlugin()
      // 3. 将组件对象,手动挂载到某一个元素上
      toast.$mount(document.createElement('div'))
      // 4. toast.$el就是对应的div
      document.body.appendChild(toast.$el)
      // 5. 挂载到原型上
      Vue.prototype.$toast = toast
      }
    
      export default obj
  8. 动态绑定图片src的地址

    可以采用import或者require的方式动态绑定,需要注意的是: 无法使用别名,只能用相对或绝对地址

  9. 问题: 项目上线nginx服务器时刷新页面出现404NotFound

    出现问题的原因: vue-router默认使用hash模式--使用URLhash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载

    问题解决: 在配置文件中加入:try_files $uri $uri/ /index.html

    nginxtry_files在你刷新完页面之后会把地址进行重定向处理,就会去找你的真实页面,找到则显示,找不到时会默认显示index页面