我的项目仓库地址:https://github.com/konglingwen94/vue-elm-sell

我的项目线上地址: http://123.56.124.33:5000

前提

自从学习了Vue后,能用Vue解决的场景用例最终我都尽可能的用Vue去实现。单纯的用例需要并没有残缺的我的项目开发流程,从中能学到的货色也是无限的。在这之前除了应用Vue做过vue-music的挪动端音乐播放器我的项目和vue-bytedanceJob(重构某独角兽互联网公司官网招聘网站)之外,本人并没有用Vue涉猎web端更简单的业务场景。

为了找一个我的项目练习,我去github上开始了搜寻,当看到https://github.com/ustbhuangyi/vue-sell这个我的项目时,感觉这个挪动端利用的一些业务场景是本人没有接触过的,于是我就照着这个利用的UI性能用本人的常识体系技术栈进行了重构,大略不到半个月的工夫,我实现了第一个commit提交到我的项目上线运行,本篇文章就从利用性能技术实现一些方面分析此我的项目的开发过程以及采到的坑。

我的项目截图

<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b5c66a54ae5?w=286&h=500&f=gif&s=1854225" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b647f0cba7f?w=286&h=500&f=gif&s=838667" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b6220974f7e?w=286&h=500&f=gif&s=1786516" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b316156fd95?w=286&h=500&f=gif&s=954705" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b33d9cb205e?w=286&h=500&f=gif&s=1187009" width="200">

我的项目技术栈

  1. 前端

    • vue开发我的项目外围框架
    • axios HTTP申请模块
    • lib-flexible 挪动端屏幕适配计划
    • better-scroll 仿IOS成果的挪动端滚动库
    • normalize.css 第三方css款式初始化模块
    • es 6/7 下一代javascript语法
  2. 后端

    • express 搭建服务端利用外围框架
  3. 开发

    • vue-cli 我的项目初始化脚手架
    • vue-devtools 我的项目开发环境调试工具
    • vscode chrome git macbookpro
  4. 部署

    • 代码托管仓库 https://github.com/konglingwen94/vue-elm-sell
    • 线上地址 123.56.124.33:5000

利用性能

  • [x] 商品页

    • [x] 商品分类导航和商品列表的联动成果
    • [x] 点击商品分类菜单展现对应商品列表信息
    • [x] 增加/删除商品到购物车
    • [x] 点击商品进入到详情页面
    • [ ] 商品增加到购物车动画成果
    • [ ] 页面滚动到对应商品类别时的题目吸顶成果
  • [x] 评论页

    • [x] 综合评论信息渲染
    • [x] 切换评论筛选项按钮展现对应的信息
    • [x] 抉择展现是否有内容的评论
  • [x] 商家页

    • [x] 商家店铺信息展现
    • [x] 珍藏店铺
    • [x] 商家实景图片具备bounce成果的滑动显示
  • [x] 利用头部

    • [x] 点击展现详情
    • [ ] 布告信息动静滚动显示
  • [x] 购物车

    • [x] 依据商品个数显示不同的状态
    • [x] 购物车商品列表
    • [x] 领取弹窗
    • [x] 清空购物车
    • [x] 减少/删除商品
  • [ ] 利用局部优化
bounce成果是指在利用中页面地位滚动到一个端点持续滑动时呈现反弹的成果,常见场景是IOS零碎利用滑动成果

性能难点

商品导航和内容的左右联动成果

成果演示

残缺的组件代码点https://github.com/konglingwen94/vue-elm-sell/blob/master/src/views/goods/index.vue。

思路

因为商品导航和内容是两个独立的滚动容器,当滚动到一个指标内容块时怎么能力激活它所关联的导航项呢?咱们晓得导航项列表和内容列表在排列程序上是统一的,如果能计算出内容滚动地位处在对应区间块的索引,也就失去了导航列表应该激活的指标索引,而后就能够用Vue数据驱动视图的思维去实现这所有。

容器的左右联动成果是指容器滚动到指标内容时激活其关联的导航菜单项并滚动到可视区域。

逻辑实现

找到要激活的指标导航项索引的第一步须要把商品内容的各个类别块在容器内的纵坐标地位存储起来(给之后找到激活的指标索引提供比拟对象),因为列表内容时动静渲染的,所以这里须要等所有数据曾经渲染实现后能力操作,上面间接看代码演示吧!

template局部

<template>    /* 这里只显示局部代码*/     <ul class="foods-list">          <li ref="foodsGroup" class="foods-group" v-for="(item,index) in data" :key="index">            <dl class="foods-group-wrapper">              <dt :class="{fixed:currentIndex===index}" class="foods-group-name">{{item.name}}</dt>              <dd                class="foods-group-item"                v-for="(food ,key) in item.foods"                :key="key"              >                 {{food.name}}              </dd>            </dl>          </li>        </ul></template>

script局部

 export default {    data(){      return {          currentIndex: 0,//导航项激活的索引          currentFood: {},          data:[],          sectionHeight: [0],//第一个高度块坐标`y`值为`0`          // 渲染实现后的值为 `[0,1281,1459,1612,2000,2270,2565,2952,3574,4436]`      }      },    created() {        request          .get("/goods")          .then(response => {            this.data = response;          })          .then(() => {            setTimeout(() => {              const sections = this.$refs.foodsGroup;                  sections.reduce((prevTotal, current) => {                const sectionHeight = prevTotal + current.clientHeight;                this.sectionHeight.push(sectionHeight);                    return sectionHeight;              }, 0);            });        });  }}

有了各个商品块的y坐标,下一步就须要注册容器元素的滚动事件了,在回调函数里通过找到实时滚动地位disanceY处在sectionHeight数组中两个相邻元素之间的地位从而就失去了待激活导航索引currentIndex的值,具体代码实现如下

<template>    <div>        <!--导航菜单-->         <scroll class="menu">            <ul class="menu-list">              <li                @tap="selectMenu(index)"                class="menu-item"                :class="{selected:currentIndex===index}"                v-for="(item,index) in data"                :key="index"              >               <span>{{ item.name}}</span>              </li>            </ul>          </scroll>                  <!--商品内容-->        <scroll ref="foodsScroll" @scroll="onFoodScroll" class="foods">        <!--这里省略商品内容模板的代码-->        </scroll>        </div></template>
export default {    // 这里省略其余代码        methods:{        onFoodScroll({ x, y }) {          const distanceY = Math.abs(Math.round(y));          for (let index = 0; index < this.sectionHeight.length; index++) {            if (              distanceY >= this.sectionHeight[index] &&              distanceY < this.sectionHeight[index + 1]            ) {              this.currentIndex = index;            }          }        }    }}
残缺的组件代码点https://github.com/konglingwen94/vue-elm-sell/blob/master/src/views/goods/index.vue。因为左右两侧的布局容器都是基于better-scroll实现的页面滚动,所以这里须要侦听better-scroll提供的scroll事件而不是浏览器原生的滚动事件。查看better-scrollscroll事件API点这里。

增加/删除 商品到购物车

成果截图

残缺代码https://github.com/konglingwen94/vue-elm-sell/blob/master/src/components/food-picker/index.vue

思路

增加商品到购物车是一个多场景的性能,因为这里的购物车性能是一个多页面联动的成果,购物车商品数量的实时更改也须要同步到商品内容页和商品详情页。从性能映射到javascript语言数据结构层面的话,不难想到对象援用传递的特点能够作为实现此性能的底层架构思路,那就让咱们去实现它吧。

实现

为了统计商品的数量。首先须要给每一个商品信息对象增加一个默认值为0count属性,增加后的对象长这样

{  "count": 0, // 此变量用来存储增加到购物车的数量  "name": "皮蛋瘦肉粥",  "price": 10,  "oldPrice": "",  "description": "咸粥",  "sellCount": 229,  "rating": 100,  "info": "一碗皮蛋瘦肉粥,总是我到粥店时的不二之选。香浓软滑,饱腹暖心,皮蛋的Q弹与瘦肉的滑嫩伴着粥香溢于满口,让人喝这样的一碗粥也感觉称心如意",  "ratings": [    {      "username": "3******b",      "rateTime": 1469261964000,      "rateType": 1,      "text": "",      "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png"    }  ],  "icon": "http://fuss10.elemecdn.com/c/cd/c12745ed8a5171e13b427dbc39401jpeg.jpeg?imageView2/1/w/114/h/114",  "image": "http://fuss10.elemecdn.com/c/cd/c12745ed8a5171e13b427dbc39401jpeg.jpeg?imageView2/1/w/750/h/750"}

因为每一个商品项都有一个增加到购物车的数量选择器性能,这样咱们间接给商品数量选择器组件设计一个名为foodInfo的对象类型props,这样在减少/缩小商品数量的时候间接操作foodInfocount属性来实现同步数据的成果。

/components/food-picker.vue 组件代码

<template>  <div class="food-picker" @click.stop>    <div class="reduce-wrapper" @click="reduce">      <i class="iconfont reduce"></i>    </div>    <div class="counter">{{foodInfo.count}}</div>    <div class="add-wrapper" @click="add">      <i class="iconfont add"></i>    </div>  </div></template><script>export default {  name: "food-picker",  props: {    foodInfo: {      type: Object,      default: () => ({})    }  },  methods: {    reduce() {      if (parseInt(this.foodInfo.count) > 0) {        this.foodInfo.count--;      }    },    add() {      this.foodInfo.count++;    }  }};</script><style lang="less" scoped>.food-picker {  min-width: 180px;  max-width: 200px;  display: flex;  align-items: center;  width: 100%;  justify-content: space-between;  .iconfont {    color: #00a0dc;    font-size: 38px;  }  .counter {    // margin: 0 20px;  }}</style>

下一个指标

基于目前曾经实现的性能,整个利用的数据都是以json文件的格局存储在服务器,服务端并没有能够用来增删改查API接口可供使用。下一步我打算做出治理后盾和服务端API用来治理前端页面的数据,使所有模块的数据都是可配置的,这样前端所渲染进去的数据也都是动静的,可能整合三端到一个我的项目也满足了当下Web全栈开发的场景须要。

总结

通过实在的开发这样一个简单交互的利用,本人对Vue在理论业务场景中的应用和了解有深刻了一步。深刻了解了Vue数据驱动视图扭转的思维,纯熟的把握了组件化开发我的项目的流程,同时也感触到所带来的便当,为本人接下来准备做的中大型项目修建好了桥梁。

反对

如果本我的项目对您学习有帮忙,请您入手点个starhttps://github.com/konglingwen94/vue-elm-sell。也心愿您持续关注我的动静https://github.com/konglingwen94,有了您的反对我会有能源开源更多乏味的我的项目。

欢送点赞和留言,谢谢!