在线电商网站--项目复盘

170 阅读3分钟

最近我们参与开发了一个在线电商项目,前端使用vue全家桶,项目功能基本开发完成。采用前后端分离形式开发,大部分功能我们都是自己写的,有部分组件我们用了elementUI,比如分页,登录、注册。有一些数据使用了mock工具,接口文档使用在线的形式,方便修改查询。

前端其实不太复杂,但是在使用vue开发时,也是遇到一些小问题,比如:参数不变重复跳转路由报错,多级分类跳转路由携带参数,

项目介绍

这是一个在线的电商web app,是一个spa应用,主要销售是奢侈品方面的东西,

主要模块:

包括首页、搜索列表、商品详情、购物车、地址管理、下单&支付、退货退款、用户注册&登录多个子模块

主题技术

使用vue全家桶+ES6++Webpack+axios等前端最新最热的技术

开发模式

采用了模块化、组件化、工程化的模式开发

技术选型

classDiagram
技术选型 --|> 前台数据处理
技术选型 --|> 前后台交互
技术选型 --|> 模块化
技术选型 --|> 项目构建 工程化
技术选型 --|> css预编辑器
技术选型 --|> 其他
class 前台数据处理{
vue
vue-router
vuex
vue-lazyload
vee-vaildate
element-ui
swiper
nprogress
}
class 前后台交互{
axios
async await
mockjs
postman
}
class 模块化{
ES6
bable
}
class 项目构建 工程化{
webpack
vue-cli4
eslint
}
class css预编辑器{
less
}
class 其他{
lodash
uuidjs
qrcode
}

API接口

全称:前后台交互接口/api

重要的概念:

  • api/接口
  • 接口文档
  • 对/调/测试接口
  • 联调
  • 前后台分离
  • mock数据

从项目中学到那些?

1、流程及开发方法

  • 熟悉一个项目的开发流程
  • 学会模块化、组件化、工程化的开发模式
  • 掌握使用vue-cli脚手架初始化Vue.js项目
  • 学会模拟json数据,实现前后端分离开发
  • 学会ES6+eslint的开发方式
  • 掌握一些项目优化技巧

2、vue插件及第三方库

  • 学会使用vue-router开发单页面应用
  • 学会使用axios与后端进行数据交互
  • 学会使用vuex管理应用组件状态
  • 学会使用swiper&vue-awesome-swiper实现页面滑动效果
  • 学会使用element-ui组件库构建页面
  • 学会使用vee-validate进行前台表单校验
  • 学会使用vue-lazyload实现图片懒加载
  • 学会使用mockjs模拟后台数据接口
  • 使用一些小的工具库
    • lodash:函数节流
    • nprogress:请求进度
    • uuid:生成唯一用户临时ID
    • qrcode:生成支付二维码

项目中遇到的一次问题

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

  • 原因:vue-router3.1.0之后, 引入了promise的语法,如果没有通过参数指定成功或者失败回调函数就返回一个promise且内部会判断如果要跳转的路径和参数都没有变化,
  • 解决办法:
    • 在跳转时指定成功或失败的回调函数, 或者catch处理错误
    • 修改Vue原型上的push和replace方法 (优秀)
// 缓存原本的push方法   ||  replace方法同理
const originalPush = VueRouter.prototype.push
// 指定新的push方法
VueRouter.prototype.push = function push(location, onResolve, onReject) {
  // 如果指定了成功或失败的回调
  if (onResolve || onReject)
  // 直接调用原本的push方法
    return originalPush.call(this, location, onResolve, onReject)
  // 没有指定成功或失败回调, 必须用catch处理
  return originalPush.call(this, location).catch((err) => {
    // 如果是重复导航产生的错误, 不再向外传递错误
    if (VueRouter.isNavigationFailure(err)) {
      // 产生的是成功的promise, 成功promise的value是err
      // resolve err
      return err
    }
    // 如果是其它原因导航的错误, 将错误向下传递
    // rethrow error
    return Promise.reject(err)
  })
}

2、解决三级分类导航跳转路由并携带对应参数的问题

  • 通过使用编程式路由导航替代声明式路由导航,避免创建组件过多,优化效率
  • 通过事件委派优化事件回调过多的问题
  • 通过标签的data-自定义属性,区分一二三级标签
<div class="sort" v-show="isShow">
    <div class="all-sort-list2" @click="toSearch">
        <div class="item" 
            v-for="(category1,index) in baseCategoryList" 
            :key="category1.categoryId"
            :class="{active: currentIndex === index}"
            @mouseenter="showCategory(index)"
        >
            <h3>
                <a href="javascript:;" 
                    :data-category1Id="category1.categoryId"
                    :data-categoryName="category1.categoryName"
                >{{category1.categoryName}}</a>
                <!-- <router-link :to="`/search?category1Id=${category1.categoryId}`">{{category1.categoryName}}</router-link> -->
                <!-- <a href="javascript:;" @click="toSearch('category1Id',category1.categoryId)">{{category1.categoryName}}</a> -->
            </h3>
            <div class="item-list clearfix">
                <div class="subitem">
                    <dl class="fore" v-for="category2 in category1.categoryChild" :key="category2.categoryId">
                        <dt>
                            <a href="javascript:;" 
                                :data-category2Id="category2.categoryId"
                                :data-categoryName="category2.categoryName"
                            >{{category2.categoryName}}</a>
                            <!-- <router-link :to="`/search?category2Id=${category2.categoryId}`">{{category2.categoryName}}</router-link> -->
                            <!-- <a href="javascript:;" @click="toSearch('category2Id',category2.categoryId)">{{category2.categoryName}}</a> -->

                        </dt>
                        <dd>
                            <em v-for="category3 in category2.categoryChild" :key="category3.categoryId">
                                <a href="javascript:;" 
                                    :data-category3Id="category3.categoryId"
                                    :data-categoryName="category3.categoryName"
                                >{{category3.categoryName}}</a>                                             
                                <!-- <router-link :to="`/search?category3Id=${category3.categoryId}`">{{category3.categoryName}}</router-link> -->
                                <!-- <a href="javascript:;" @click="toSearch('category3Id',category3.categoryId)">{{category3.categoryName}}</a> -->
                            </em>
                        </dd>
                    </dl>
                </div>
            </div>
        </div>
    </div>
</div>

未完待续...