zoukankan      html  css  js  c++  java
  • 全栈之路-微信小程序-SKU开发(代码)

      SKU开发是小程序中最难的一部分,思路在分析中已经记录过了,这里主要看一下代码的实现,感觉老师写的代码太棒了,很优雅!主要想记录一下写代码的思路,对面向对象编程的实践。

    一、代码结构的分析

    1、说明几个关键词

    搞清楚sku的概念,搞清楚我们抽象出来的realm组件、fence组件、cell组件以及他们对应的模型类,这里模型类放到models文件夹中

    realm组件 --- fence-group.js中的FenceGroup模型

    fence组件 --- fence.js中的Fence模型

    cell组件 --- cell.js中Cell模型

    除此之外,还有

    矩阵的处理模型:matrix.js中的Matrix模型

    总控制模型(负责方法的调用):judger.js中的Judger模型

    sku-code处理模型:sku-code.js中的SkuCode模型

    2019年12月10日11:04:41截止,可能后续还会有处理sku规格值的状态的模型,后续再补充...

    2、分析他们之间的联系(做的图示)

    说明:

    图中所示的箭头的流向是从用户的角度来看,当点击规格值进行选择时,数据的流向

    感想总结:这个结构这样抽象出来,感觉太清晰了,彼此之前是独立的,可扩展的,但是彼此之间是有联系的,各司其职,哇,感觉这样写出来的代码太美好了,原来写代码可以这么舒服,好的代码,好的架构真的让人耳目一新,回味无穷啊!今后奋斗的方向,写出好的代码,优雅而强大!

    二、代码的编写

    这也不是完整的SKU代码,只是一部分的代码,只是用来记录一下整个SKU开发的代码的结构,看一下简单的代码(从realm组件到cell组件),实现SKU规格值的提取(SKU状态的确定代码就不记录了,太复杂了,不过之后可能记录一下其中编码思路),顺序是按照图示的顺序(开发的过程,并不是严格按照这个顺序进行编码的,开发是按照从fence-group出发,细化,抽象出fence,再进一步细化,抽象出cell)  

    1、cell组件

    这里不考虑SKU规格值的状态的确定,所以cell组件的代码就相对来说特别简单,只是来负责将规格值显示出来(代码中没有样式代码)

     1 // index.wxml代码
     2 <!--规格值组件-->
     3 <view bind:tap="onTap" class="container">
     4     <view class="inner-container">
     5         <text>{{cell.title}}</text>
     6     </view>
     7 </view>
     8 
     9 // index.js代码 创建cell属性
    10 properties: {
    11     cell:Object
    12 },

    2、cell模型(cell.js)

    创建Cell类,有构造方法以及id(规格值id)和title(规格值名称)两个属性

     1 class Cell{
     2     id // 规格值的主键id
     3     title // 规格值的名字
     4 
     5     constructor(spec){
     6         this.title = spec.value
     7         this.id = spec.value_id
     8     }
     9 }
    10 
    11 export {
    12     Cell
    13 }

    3、fence组件

    fence组件需要引入cell组件,需要用fence属性来传递数据

     1 // index.wxml
     2 <view class="container">
     3     <!--规格名-->
     4     <view class="title">{{fence.title}}</view>
     5     <!--规格名下的所有规格值-->
     6     <view class="row-container">
     7         <block wx:for="{{fence.cells}}" wx:key="{{index}}">
     8             <!--规格值组件-->
     9             <s-cell class="cell" cell="{{item}}"></s-cell>
    10         </block>
    11         <view class="hr"></view>
    12     </view>
    13 </view>
    14 
    15 // index.js
    16 properties: {
    17     fence: Object
    18 },
    19 
    20 // index.json
    21 {
    22   "component": true,
    23   "usingComponents": {
    24       "s-cell":"/components/cell/index"
    25   }
    26 }

    4、fence模型(fence,js)

    创建Fence类,有构造方法,cells属性(存放一个规格名下的一组规格值),specs属性(spu(商品)的一个确定的规格值的组合,比如:金属灰-七龙珠-小号 S),title(规格名名称)以及id(规格名id)以及初始化cell的方法

     1 import {Cell} from "./cell";
     2 
     3 class Fence {
     4 
     5     cells = []
     6     specs
     7     title // 规格名的名字
     8     id // 规格名的主键id
     9 
    10     constructor(specs) {
    11         this.specs = specs
    12         this.title = specs[0].key
    13         this.id = specs[0].key_id
    14     }
    15 
    16     init() {
    17         this._initCells()
    18     }
    19 
    20     _initCells(){
    21         this.specs.forEach(s=>{
    22             // 去重判断
    23             const existed = this.cells.some(c=>{
    24                 return c.id === s.value_id
    25             })
    26             if(existed){
    27                 return
    28             }
    29             const cell = new Cell(s)
    30             this.cells.push(cell)
    31         })
    32     }
    33 }
    34 
    35 export {
    36     Fence
    37 }

    补充说明数组(Array)中的some方法:

    链接地址详解:https://www.runoob.com/jsref/jsref-some.html

    some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。

    some() 方法会依次执行数组的每个元素:

    • 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
    • 如果没有满足条件的元素,则返回false。

    注意: some() 不会对空数组进行检测。

    注意: some() 不会改变原始数组。

    5、realm组件(对应着fence-group.js)

    realm组件需要引用fence组件,需要通过spu属性来传递数据,并且需要监听spu

     1 // index.wxml代码
     2 <view class="container">
     3     <view>
     4         <image></image>
     5     </view>
     6     <block wx:for="{{fences}}" wx:key="{{index}}">
     7         <s-fence fence="{{item}}"></s-fence>
     8     </block>
     9     <view class="counter-container">
    10         <!--<l-counter></l-counter>-->
    11     </view>
    12 </view>
    13 
    14 // index.js代码
    15     properties: {
    16         spu: Object
    17     },
    18 
    19     data: {
    20         judger:Object
    21     },
    22 
    23     observers: {
    24         'spu': function (spu) {
    25             if (!spu) {
    26                 return
    27             }
    28             const fenceGroup = new FenceGroup(spu)
    29             fenceGroup.initFences()
    30             // judge在这里并没有用到
    31             // const judger = new Judger(fenceGroup)
    32             // this.data.judger = judger
    33             this.bindInitData(fenceGroup)
    34         }
    35     },
    36     methods: {
    37         bindInitData(fenceGroup) {
    38             this.setData({
    39                 fences:fenceGroup.fences
    40             })
    41         },
    42     }    
    43 
    44 // index.json
    45 {
    46   "component": true,
    47   "usingComponents": {
    48     "s-fence":"/components/fence/index"
    49   }
    50 }

    补充说明一下,小程序中的observer监听函数的详解:

    组件数据字段监听器,用于监听 properties 和 data 的变化,参见 数据监听器

    数据监听器链接地址:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/observer.html

    6、fence-group模型(fence-group.js)

    创建FenceGroup类,创建spu属性、skuList属性以及fences属性,还有初始化的fence方法(这里用到了矩阵中的转置方法,具体就不记录了)

     1 import {Matrix} from "./matrix";
     2 import {Fence} from "./fence";
     3 
     4 class FenceGroup {
     5     spu
     6     skuList = []
     7     fences
     8 
     9     constructor(spu) {
    10         this.spu = spu
    11         this.skuList = spu.sku_list
    12     }
    13 
    14     initFences() {
    15         const matrix = this._createMatrix(this.skuList)
    16         const fences = []
    17         // 进行矩阵的转置操作
    18         const AT = matrix.transpose()
    19         AT.forEach(r => {
    20             const fence = new Fence(r)
    21             fence.init()
    22             fences.push(fence)
    23         })
    24         this.fences = fences
    25     }
    26 
    27     _createMatrix(skuList) {
    28         const m = []
    29         skuList.forEach(sku => {
    30             m.push(sku.specs)
    31         })
    32         return new Matrix(m)
    33     }
    34 
    35 }
    36 
    37 export {
    38     FenceGroup
    39 }

    说明:矩阵的思想其实在这里简化了实现思路,可以看一下具体的矩阵是如何进行装置操作的,可看一下百度百科中的说明:

    链接地址:https://baike.baidu.com/item/转置矩阵

    三、重要总结

    数据的流向问题在啰嗦一下:

      一切都是从商品的详情页面进行发起的,当用户点击商品的时候,跳转到详情页面,用户点击加入购物车的功能,商品的规格信息进行显示,初始化商品的规格信息,这里触发了realm组件的监听spu的方法,从而引发多米诺骨效应,从FenceGroup模型的创建,到Fence模型的创建,再到Cell模型的创建,当数据最终创建之后,在通过组件一步一步的渲染。最终呈现在用户的面前就是可选的一组规格(当然这个功能完善之后,用户看到的是一组选择好的规格路径,这里没实现),这就是完整的一个过程,当然仅仅只是一个规格值的处理提取的过程。

     内容出处:七月老师《从Java后端到全栈》视频课程

    七月老师课程链接:https://class.imooc.com/sale/javafullstack

  • 相关阅读:
    jQuery的几个Grid插件简单比较
    位运算符
    Unity --- 纹理压缩基本知识点
    Unity---资源管理中不同资源的路径获取方式
    Unity--- 资源路径问题
    数据结构 --- 基本概念
    《UnityShader入门精要》学习笔记之渲染流水线
    UnityShader中的语义相关
    补充一下角度制与弧度制的相关知识
    NGUI中处理层级问题的几个方法总结
  • 原文地址:https://www.cnblogs.com/ssh-html/p/12011842.html
Copyright © 2011-2022 走看看