[TOC]

商城项目

划分目录

├─assets  资源
│  ├─css
│  └─img
├─common  用于存放公共的js文件(变量、方法等)
├─components  用于存放公共的组件
│  ├─common        能复用的组件
│  └─content  能复用但只和内容相关的组件
├─network  网络请求
├─router  路由
├─store  状态(Vuex)
└─views  主要的视图
    ├─category
    └─home

配置别名

vue.config.js 用于配置一些自定义的配置

// vue.config.js

module.exports = {
  configureWebpack: {
    resolve: {
      // 配置别名
      alias: {
        // @ 别名在默认配置中已经有了 @: 'src'
        'assets': '@/assets',
        'common': '@/common',
        'components': '@/components',
        'network': '@/network',
        'store': '@/store',
        'view': '@/view',
      }
    }
  }
}

编码风格

.editorconfig 文件用于统一编码风格

root = true

[*]
charset = utf-8
# 缩进风格
indent_style = space
# 缩进的大小为 2 个空格
indent_size = 2
# 在行尾换行
end_of_line = lf
# 在最后插入一个新的行
insert_final_newline = true
# 清除无效的空格
trim_trailing_whitespace = true

引入 CSS

  • 引入 normalize.css 用于统一浏览器样式和一些默认样式
  • 引入 base.css 一些基本样式

最后在 App.vue 中导入 base.css

/* base.css */
@import "./normalize.css";


:root {
  --color-text: #666;
  --color-high-text: #ff5777;
  --color-tint: #ff8197;
  --color-background: #fff;
  --font-size: 14px;
  --line-height: 1.5;
}

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","MIcrosoft YaHei","微软雅黑",Arial,sans-serif;
  user-select: none; /* 禁止用户鼠标在页面上选中文字/图片等 */
  -webkit-tap-highlight-color: transparent; /* webkit 是苹果浏览器引擎,tap点击,highlight 背景高亮,color 颜色,颜色用数值调节 */
  background: var(--color-background);
  color: var(--color-text);
  width: 100vw;
}

a {
  color: var(--color-text);
  text-decoration: none;
}

.clear-fix::after {
  clear: both;
  content: '';
  display: block;
  width: 0;
  height: 0;
  visibility: hidden;
}

.clear-fix {
  zoom: 1;
}

.left {
  float: left;
}

:right {
  float: right;
}

模块划分

image.png

例如该案例用于展现内容的主要视图分为首页、分类、购物车、我的,tab-bar 为公共组件

// App.vue
<template>
  <div id="app">
    // 用于展示划分好的 view
    <router-view></router-view>
    // 公共的 tab-bar 组件
    <main-tab-bar></main-tab-bar>
  </div>
</template>

<script>
import MainTabBar from "components/content/mainTabbar/MainTabBar";

export default {
  name: "App",
  components: {
    MainTabBar,
  },
};
</script>

路由映射

配置主视图(views)的路由关系

import Vue from 'vue';
import VueRouter from 'vue-router';

// 懒加载
const Home = () => import('../views/home/Home')
const Category = () => import('../views/category/Category')
const Cart = () => import('../views/cart/Cart')
const Profile = () => import('../views/profile/Profile')

Vue.use(VueRouter)

const routes = [
  {
    path: '',
    redirect: '/home'
  },
  {
    path: '/home',
    component: Home
  },
  {
    path: '/category',
    component: Category
  },
  {
    path: '/cart',
    component: Cart
  },
  {
    path: '/profile',
    component: Profile
  },
]

const router = new VueRouter({
  routes,
  mode: 'history'
})

export default router

网络请求

将 home 相关的网络请求封装起来,这样就能将网页和网络请求分离

// home.js
import { request } from "./request"

export function getHomeMultidata() {
  return request({
    url: '/home/multidata'
  })
}

使用

// Home.vue
import { getHomeMultidata } from "network/home.js";

created() {
  // 1.请求多个数据
  getHomeMultidata().then((res) => {
    this.banners = res.data.data.banner.list;
    this.recommends = res.data.data.recommend.list;
  });
},

首页开发

  • navbar 的封装
  • 轮播图
  • 推荐信息
  • 网络数据的请求
    • 封装 axios 实例 ```javascript // network/request.js import axios from ‘axios’;

export function request(config) { // 1.创建 axios 实例 const instance = axios.create({ baseURL: ‘http://123.207.32.32:8000‘, timeout: 50000 })

// 2.axios 拦截器 instance.interceptors.request.use(config => { return config }, err => { console.log(err); })

instance.interceptors.response.use(res => { return res }, err => { console.log(err); })

// 3.发送真正的网络请求 return instance(config) }


- 将首页相关的网络请求单独封装
```javascript
// network/home.js
import { request } from "./request"

export function getHomeMultidata() {
  return request({
    url: '/home/multidata'
  })
}
  • 将请求的数据保存下来 ```vue // Home.vue

    
    - **本周流行和推荐**
    - **tab-control**
       - 数据请求
       - 单击切换
       - 吸顶效果
       - 状态同步
    - better-scroll 封装
       - 上拉加载
       - better-scroll 的滑动 bug 处理(事件总线)、
       - 防抖
    - 封装 back-top
    - 保持 home 的状态
       - keep-alive
       - 保存当前滚动位置的Y值
       - activated 时还原状态
    <a name="9JUqI"></a>
    ## 商品详情
    
    - 通过 iid 获取数据
    - navBar 复用
    - swiper  的复用
    - baseInfo 的封装(使用 class 进行汇总)
    - shopInfo  的封装
    - goodsInfo 的封闭
       - 图片加载完只发送一次事件
    - paramInfo
    - commontInfo
       - 格式化时间
    - 图片加载完成问题(mixin)
    - 标题和内容的联动效果
       - index
       - offsetTop
    
    ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2332117/1609729117658-13df7a59-1520-4675-8070-eae205a41892.png#align=left&display=inline&height=206&margin=%5Bobject%20Object%5D&name=image.png&originHeight=206&originWidth=385&size=71295&status=done&style=none&width=385)
    
    - 底部工具栏的封装
    - 回到顶部的抽取(mixin)
    - 点击加入购物车(Vuex)
       - Vuex 代码的重构
    - 显示成功加入购物车(Promise)
       - 将 actions 映射到 methods
    
    <a name="6Rpru"></a>
    ## 购物车
    
    - 导航栏
       - 将 getters 映射到 computed
    - 商品展示
    - 封装 checkButton
    - 商品的选中和不选中(修改模型对象)
    - 底部工具栏
       - 合计
       - 选择数量
       - 全选按钮
    
    <a name="3afddf73"></a>
    ## 封装 toast
    
    - 插件式
    - 在 main.js 中安装插件(原理是会执行插件中的 install 函数)
    - 在 toast 组件目录下新建 js 文件
    - 导入 toast 组件
    - ....
    
    <a name="hsONx"></a>
    ## fastClick
    
    减少移动端 300ms 延时
    
    安装
    > npm install fastclick --save
    
    
    使用
    ```javascript
    // main.js