移动端农机商城项目前端开发笔记

  • 项目后端文档点此

  • 项目结构的创建: 基于 VueCLI v3.11.0

  • 前端路由模式 : hash

  • 项目页面渲染效果基于 Vant 组件库

    • babel7

    • 配置按需引用 vant 组件

  • 本项目采用的适配不同移动端屏幕的方法

    • rem & em

    • flex 布局

  • get 和 post 发送请求的区别

    • get : 获取数据 , 请求参数可见 , 通过请求头发送数据 , 数据量小…

    • post : 提交数据 , 请求参数隐藏 , 通过请求体发送数据 , 数据量大…

  • 判断空对象的方式

        let obj = {}
        JSON.stringify(obj) == '{}'
    
  • 路由跳转的两种方式,我使用的vant组件库的Tabbar组件

    • Tabbar组件 :

    • Vue Router :

  • Vue Router 传参方式汇总

    • 匿名路由 ( 类似于 GET 方式传参 , 参数拼接在URL后 , 用户刷新页面后仍可获取到参数 )

          // src/router/index.js
          {
            path: '/detail',
          }
      
          // src/views/Category.vue
          this.$router.push({
            path: '/detail',
            query: {id: ...}
          });
      
          // src/views/Detail.vue
          created() {
            console.log(this.$route.query.id)
          }
      
    • 具名路由 ( 类似于 POST 方式传参 , 用户刷新页面后参数丢失 )

          // src/router/index.js
          {
            path: '/detail',
            name: 'detail',
          }
      
          // src/views/Category.vue
          this.$router.push({
            name: 'detail',
            params: {id: ...}
          })
      
          // src/views/Detail.vue
          created() {
            console.log(this.$route.params.id)
          }
      
    • path可动态配置的路由 ( 参数拼接在URL上 , 用户刷新页面后仍可获取到参数 )

          // src/router/index.js
          {
            path: '/detail/:id',
          }
      
          // src/views/Category.vue
          this.$router.push(`/detail/${id}`)
      
          // src/views/Detail.vue
          created() {
            console.log(this.$route.params.id)
          }
      
  • 首页头部导航栏

    • 注意: JS代码添加的内联样式会显示在chrome调试工具的 element.style

    • 如下方式设置的样式具有最高权重值

      	elem {
        		style: xxx!important;
       	}
      
  • 首页轮播图

    • 宽高被强制固定

          <van-swipe class="swipe">
            <van-swipe-item>
              <img/>
            van-swipe-item>
          van-swipe>
      
      	.swipe {
      	     height: 3.6rem;
      	     img {
      	        width: 100%;
      	        height: 100%;
      	     }
      	 }
      
    • 采用图片懒加载

          import { Lazyload } from 'vant'
          Vue.use( Lazyload )
      
      	<img v-lazy="imgSrc"/>
      
  • 首页热门商品

    • 使用插件 : Vue-Awesome-Swiper

      	npm install vue-awesome-swiper --save
      
      	// mount with component
          import 'swiper/dist/css/swiper.css'
          import { swiper, swiperSlide } from 'vue-awesome-swiper'
          export default {
            components: {
              swiper,
              swiperSlide
            }
          }
      
    • 根据插件文档 swiper-api 设置一页展示 3 条热门商品数据

      	<swiper :options="swiperOption" />
      
      	export default {
            data() {
              return {
                swiperOption: {
                  slidesPerView: 3
                }
              } 
            }
          }
      
  • 首页推荐商品

    • 使用flex布局

          .parent {
            display: flex;
          }
          .son {
            flex-basis: 45%; // 设置宽度, 优先级比 width 高
          }
      
  • 商品分类页面

    • 使用 van-col 栅格布局

    • 改变选中的商品分类交互效果实现方式

          <li
            :class="{active: index == active}"
            @click="activeHandler(index)"
          >{{ item.typeName }}li>
      
          .active {
            color: #fff;
            background-color: rgb(25, 137, 251);
          }
      
          data() {
            return {
              active: 0 // 默认选中第一种商品分类
            }
          }
          methods: {
            // 改变选中的商品分类
            activeHandler(index) {
              this.active = index
            }
          }
      
    • 商品列表使用 van-list

    • 依据文档配置上拉加载和下拉刷新

    • 商品名称只显示两行 , 多余内容打点显示

        .list-item-name {
          display: -webkit-box;
          -webkit-box-orient: vertical;
          -webkit-line-clamp: 2;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      
  • 前后端通信采用基于Promise的HTTP库 : Axios

    • 安装

      	npm install axios --save
      
    • 引入 axios 的两种方式 ( 采用第一种 )

      • On Vue.prototype

            // in main.js
            import axios from 'axios'
            Vue.prototype.$axios = axios
        
            // in component to get axios
            this.$axios
        
      • In component

        	import axios from 'axios'
        
    • axios 处理并发请求的方式

      • axios.all()

        • 按照请求的顺序返回结果数组
      • axios.spread()

        • 处理结果数组
            axios.all([func1(), func2(), func3(), ...]).then(
              axios.spread((res1, res2, res3, ...) => {
                // ...
              })
            )
        
  • 测试开发阶段生成随机数据模拟后端接口拦截Ajax请求使用 Mock.js

    • 安装

      	npm install mockjs --save-dev
      
    • 定义

      	@/mock
      
    • 引入

          // main.js
          import '@/mock/mock.js'
      
  • 统一配置后台接口 & 使用方式

    	@/service.config.js
    
      // in component
      import api from '@/service.config.js'
      axios({
        method: 'get',
        url: api.getSwipeItems
      })
    

我的一点思考

保存成功登陆的用户信息的方案

  • 由于本项目只是为了复习巩固技术知识,所以我采用了方法四

    • 方法一 : Cookie-Session-Redis

      • 我实现的这种方式的代码请移步此处
    • 方法二: Json Web Token

      • 我实现的这种方式的代码请移步此处
    • 方法三 : H5 本地化存储方案

      • localStorage

      • sessionStorage

      • 我总结了这俩的异同

    • 方法四: Vuex

      • 保存的信息会在页面刷新后被清除掉

      • 该功能中 actions 的使用单纯是为了练习通过 actions 派发 commit 来调用 mutations 的方法来改变 state 中的数据 , 而 actions 的真正意义在于其中可以书写异步代码 , mutations 是唯一可以改变 state 中数据的方法 , 其中只能书写同步代码 。

加入购物车的两种思路

  • 思路 1、点击加入购物车后 , 将商品信息保存在本地存储 , 购物车页面可从本地存储中读取商品信息并展示 , 在用户点击提交订单结算的时候再判断用户是否登录

  • 思路 2、点击加入购物车后 , 判断用户是否登录 , 只有登陆成功的用户才可以将商品信息加入到数据库中的购物车表中 , 在购物车页面读取数据库展示信息

    • 计算购物车总价使用计算属性 computed

      • 当一个属性依赖于多个属性的值的时候适合使用该属性

      • 只要其关联的属性值不发生变化,就可直接从缓存中取出上一次计算的值使用


项目优化

  • 刷新页面后,优化FooterBar组件的默认选中,使用 sessionStorage

        // 依据vant文档说明,切换标签时会触发change事件,故给Tabbar组件绑定change事件
      
        // FooterBar.vue
        changeHandler(active) {
          SessionStorage.setItem('active', active);
        }
      
        created() {
          this.active = parseInt(SessionStorage.getItem('active'));
        }
    
  • 使用 vue2.x 用于保留组件状态或避免重新渲染的组件 keep-alive

    	// App.vue
      <keep-alive>
        <router-view v-if="$route.meta.keepAlive">router-view>
      keep-alive>
      <router-view v-else="!$route.meta.keepAlive">router-view>
    
    	// /@/router/index.js 中指定需要被缓存的组件的路由
        meta: {
          keepAlive: true
        }
    
  • 路由组件懒加载

        {
          path: '/',
          component: () => import("@/views/Home")
        }
    
  • 增添404错误组件 (@/views/Error.vue)

  • 项目打包和分析(–report)

        vue.config.js // vue-cli配置的核心文件
      
        "build": "vue-cli-service build --report" // package.json
    
  • gzip压缩项目

    	npm install compression-webpack-plugin --save-dev
    

BUG 记录

  • 将 position : fixed; 改为 position : absolute; 就可以触发 load 事件

  • 取消首次加载数据就触发 load 事件,添加 :immediate-check="false

  • 否则如下代码报错,因为首次加载组件的时候 this.productTypes 和 this.productList 都为空数组

     loadMoreData() {
       this.getProductList(
         this.productTypes[this.active].typeId,
         this.productList.length,
         // ...
       )
     }
    
  • 在实现下拉刷新功能时

  • 由于 van-list 设置了 position: absolute;导致父元素 塌陷

  • 故已将如下 css 代码从 迁移至 的父元素

      position: absolute;
      right: 0;
      top: 1rem;
      bottom: 1rem;
      overflow-y: scroll;
    

你可能感兴趣的:(移动端农机商城项目前端开发笔记)