慕慕家政小程序

传统架构与前后端分离架构

传统架构优点:更有利于浏览器命中静态页面及服务端返回的HTML页面,搜索引擎SEO友好

                缺点:直接生成html页面,那么终端需要有浏览器来渲染页面,导致实现的终端设备单一

前后端分离架构优点:服务端返回json数据,前后端分离,接口调用灵活

                缺点:由于服务端不直接返回一个页面,而浏览器大部分无法解析js,导致访问者无法搜索到想要的页面

实现切换tab栏

给wxml定义好循环遍历的数组DOM

然后再js里面定义一个data为判断变量,变量值跟着点击事件event.currentTarget.dataset.index

DOM元素wx:if判断变量是否等于当前元素的index值

记得在DOM元素设置属性data-index="{{index}}" 不然取不到

监听手指滑动切换页面

插槽知识点

解决问题:内容不确定、样式不确定

要不要在插槽外面嵌套view,取决于:需不需要在组件内实现对该插槽的样式书写,不一定有的的插槽不需要在组件内写样式,在哪里用就在那里写样式就可以了

什么时候使用请求数据什么时候定义js数据?

当数据不多时,且后端接口返回的数据无法直接取到想要的数据(有,但需要自己筛选),这时候可以酌情自己定义js数据

比如慕慕到家服务广场的服务类型导航栏,只有三种服务类型(全部,在提供,正在找),可以用js定义数组,遍历数组即可

注意:这种js数据一般定义在使用的page或component上,不然会降低组件的通用性

重构知识点

复用性高的代码,整理成组件:不止是html内容可以在组件里面更改,css样式也可以,可以在html里设置内联样式,然后通过js来定义属性可以实现从外部传入自定义样式;也可以设置显示状态组件,通过wx:if="{{}}"实现

可以设置成组件的东西:

加载成功与加载失败,封装一个show-status组件

使用不同的字体图标,封装wxss(从iconfont拿到的代码,图一)、html和css(通过给icon组件传不同的属性实现使用不同的iconfont,图二)

骨架屏的使用

记得在project.config.json里面配置骨架屏字段skeletonConfig

减少使用硬编码

方便后续维护,项目迭代

组件

分类:通用组件和业务组件

通用组件:和别人没关系,自己干自己的,如数据在自己这,绑定的事件也不包括其他组价的自定义事件

很多东西都可以设置为组件

屏幕兼容性组件

状态组件,当没有时显示暂无

字体图标组件,可以封装在一起,通过传名字参数实现不同icon

开发中应该避免的问题

一.js与html的频繁交互如事件通知(比如touch事件),如果有数据绑定甚至会导致页面频繁渲染,浪费资源

用wxs可以减少不必要的逻辑层与页面层的交互

wxs使用场景

1.如上,频繁地js与页面的交互时

一般用wxs文件而不直接写在wxml里,不然会导致无法复用

2.需要对数据进行复杂的格式化处理时

3.处理后端数据返回的枚举值,枚举成字符串,比如状态码变文字状态

总的来说,wxs的使用场景偏向于渲染时候对数据进行转换

wxs通信

利用在wxs里返回值

wxs响应小程序事件 ownerInstance.callMethod('响应的事件名',要传递的数据)

二.在js文件生命周期函数里面实现业务,这一般是一个入口,不应该实现过多的业务,一般在这里调用一个个函数

解决方法:在js文件里把业务定义成一个个私有函数

Or

对业务或数据进行归纳总结,最终对外提供若干函数方法,即Js面向对象机制:模型类

模型的意义:分离调用与内部实现,实现功能解耦,隔离会变化的部分(如请求的域名)

三.慎用面向对象类(如model)的静态属性

静态属性相当于共享数据,开发时被多个地方调用时,后续可能数据莫名其妙就变了,是个大隐患

四.字符串和变量拼接

尽量用模板字符串,用加号容易导致出错

导出方式不同,导入方式不同

默认导出时,import xxx from "path" xxx不需要加花括号

命名导出时,import {xxx} from "path" xxx需要加花括号 

回调函数解决异步响应问题

app.json是个好东西

通用的组件如icon组件,可以定义在app.json里面,这样所有components和pages都能用,不用重复定义了

面向对象的意义

当一个对象有不同的调用,或者调用时对象参数应该不同时,可以使用重置函数reset()实现不同的调用

如上拉触底得到新数据和下拉刷新得到最新数据

在同一个service对象model里面用reset()方法,可以实现service在上拉触底和下拉刷新等不同场景的应用。

一个类里面使用实例方法还是静态方法

使用场景:

有状态(属性)就用实例方法,实例方法可以this.xxx获取到状态,没有状态就用静态方法

原理:

实例方法本质上是在调用实例对象的方法,而静态方法是在调用类方法

静态属性

静态方法可以调用静态属性,静态属性是共享的,不要随便调,所以开发时候一般不用静态方法调用静态属性,总结:要获取到状态还是使用实例方法

联动的原理

后端传入index参数不同,请求数据一样,传参不同获得不同的数据(如点击不同tab或category得到不同panel数据)

微信开发者工具——开发辅助骨架屏

在app.json里面配置骨架屏字段

配完在小程序生成骨架屏文件,然后在要实现骨架屏页面导入文件即可

节流与防抖函数

节流:规定时间内只执行一次

防抖:只执行最后一次

闭包与this

这里的this指向最后一次调用function的地方,即使用节流函数的page页面,把this指回page

两个page之间的数据通信

注意在页面中调用接口的形式不同,比如两个相关页面(慕慕service和service-detail)的数据调用同一个接口,那么需要实现两个page页面的数据通信

以下是实现的方法

1.缓存:在有数据的page页面设置setStorageSync,需要拿数据的页面getStorageSync

        缺点:实时性差,所以推荐使用只拿index值,传index获得不同的数据,如下

两个相关页面(旧岛book和book-detail)的数据调用不同接口(book页面调用hot-list的api,book-detail调用detail、comment、likeStatus的api),通过book索引实现传参调用api,传参不同那么获得的detail数据不同,可以点击不同书本封面拿到不同书本detail数据

以下是实现方法

1.页面的options:有数据的页面可以通过在路径中传参xxx,让没有数据的页面可以通过options.xxx拿到,xxx是指需要传的index键

相关页面的跳转:通过点击跳转路由传递参数

跳转前页面(即有数据的页面)

使用wx.navigateTo(

        url:'url?data_index=' + data.index_value 

)

注意:data_index的命名由后端固定了,记得看看叫啥

css样式问题

一、通过给两个不同大小的元素,各自包裹在不同的container,这两个container设置align-self:center可以实现两个不同大小的元素对齐

比如用户头像和用户昵称显示的时候应该对齐

二、

<view class=“row”></view>

<view class=“row”></view>

<view class=“row”></view>

每个row本来就是column排列,不用给外层加column,可以给row直接定义flex-direction:row 和 justify-content:space-between,大部分是就可以设置,不是的多用一个view包裹起来就可以了

存本地和发起一个新的请求

存本地:更新相对不频繁的数据,比如当前登录的用户id

发请求:实时性高的数据,比如某个服务的信息(可能随时会更改,比如服务的状态)

提高可维护性的方法

再次强调分层面向对象的好处:分层model,让调用者不需要知道model的实现,方便下次model的改变

避免硬编码:采用enum文件夹枚举法

在model文件里面引入类(如utils/http.js)和使用继承(如extends base基类)

这两个都能引入,那么应该用哪个呢?

首先,导入格式上,继承会比引入更方便,this.xxx就可以取到继承的类的对象。如果不想new就用继承;

其次,使用对象上,继承比较偏向给公共类,即很多地方都要用到的类使用,毕竟model只是一个分离实现的包,有的实现类并不常用,对于这种类,推荐在一个调用者page的js里引入类即可

api专项

图片预览api

urls:一个数组,此次预览访问哪些图片

current:图片,用数组[index]拿到,其中index获取如下

点击图片拿到索引,进而显示图片

设置自定义属性data-id="index",获得数组的索引,进而点击事件event.currentTarget.dataset.id拿到图片索引,并进行显示

swiper组件

在这个组件里不能定义class样式!定义了用不了

多插槽记得在js文件上加上配置

options: {

        multipleSlots: true

}

当后端没返回汇总数据但又需要展示时

在定义一个方法,调用原来的api之后手动用unshift等数组分进行数据添加

定义一个触摸切换功能

步骤:

首先搞清楚是哪一个js文件需要触摸切换页面,如本案例中的tab.js需要切换,所以先在js里定义切换函数

该切换函数用direction进行切换

而direction需要用wx的触摸事件(touchstart和touchend)计算出数据

数据得出后,由于wxs的特性:可以使用调用者的函数,即tab.js的handleTouchMove方法,且通过该函数传数据direction:ownerInstance.callMethod('handleTouchMove',{direction})

串起来就是一个触摸切换功能

特别注意:当时哦你wxs方法的时候,记得给wxs命名.方法外面加上花括号。毕竟人家是变量来着!

异常与错误

区别:

异常,会中断后续代码的执行

错误则不会

为了方便调试和控制代码的执行顺序,我们可以将res.data.message抛出异常

异常需要被捕获的格式:try {需要成功但可能不能成功的语句} catch{不成功的处理}

模块要注意static方法是不能被实例访问到的!!

setData异步

this.setData是异步的,所以我们需要用的更新的数据时,需要确认是否在一个函数内,不是的话它们的执行顺序是不确定的

页面间通信emit

在给数据的页面触发事件login

获得数据的那一边监听

js的深拷贝和浅拷贝

对于引用数据类型如对象,我们无法直接赋值,因为得到的是地址,解决方法有两个

一是转换成普通数据类型的赋值,数据 = 引用数据类型.属性

二是使用第三方类库Lodash的cloneDeep()方法

对wx.uploadFile进行二次封装,作用效果类似于http.js

api参数:url(文件上传路径),filePath(文件的路径),name(唯一标识,一般为key)

uploadFile没有进行promise的转换,所以取res的时候,需要自己序列化,即JSON.prase(res.data)这样才能取得到特定的值如error_code等

组件的生命周期函数和使用者的生命周期函数执行顺序不一定

在这方面可能会发生逻辑冲突,可以通过打印日志的方式检查两个地方的执行顺序

weui表单组件的使用

表单组件mp-form 和 mp-cell

表单常用元素标签:(嵌套于mp-cell,在mp-cell中也可以使用自定义组件)

1.picker自带change事件,可嵌套view,是显示的数据

2.switch勾选标签

3.textarea文本标签

4.input表单输入标签

5.button按钮

表单数据渲染

分两种,展示初始化信息(修改表单)和初始化信息为空(创建新表单)

修改表单:需要传一个值(对象)给formData,且需要考虑深拷贝浅拷贝问题

对象传参

当传参是一个对象时,需要先转换成字符串,作为参数传过去,然后在另一边转换回对象再接收该对象参数

表单校验

首先配置rules(在data里配置)

再通过获取组件实例(即表单组件),注意,通过给wxml标签配置id以及rules规则,然后在js文件this.selectComponents(id:'#xxx')获取

表单组件mp-form会有一个方法,validate,通过这个方法,里面调用箭头函数,可以拿到校验结果

组件与页面间通信的另一种方法:

在外部直接调用自定义组件内部的方法,这时候就可以通过this.selectComponent('#页面元素id') 方法获取组件实例对象,这样就可以直接访问组件的任意数据和方法

wxml显示提示

第一步是tips,可以通过组件mp-toptips来显示,属性有msg,show,type

第二步是给每一项cell单独配置show-error和prop属性

在使用lib第三方库的时候,由于moment.js无法实现切换页面后重置掉校验不通过,所以我们需要手动通过定义条件渲染并且在生命周期函数里面(show和hide)通过更新showForm的值,来手动实现检验信息清空

但是这又带来另一个问题,即我们在调用chooseImage时,由于该原生api的特性,选择上传图片时,会调用hide,选择结束后会调用show生命周期函数,所以当选择结束后,创建服务的表单数据会清空

解决方法:

在初始化表单or更改showForm为false之前增加判断条件,通过一个值来动态决定chooseImage时页面不切换即可

单例模式

希望实例化对象在全局内只有一份时,可以使用单例模式

即定义一个静态属性为空

一个静态方法,当没有该静态属性时,则给该静态属性赋值一个实例(该小程序是Tim实例)

SDK初识

sdktim实例在Tim的构造函数里面创建

通过get方法可以让Tim实例方法获得sdk实例,避免创建sdk重复代码

SDK即时通信的getMessageList(异步,返回promise)需要传三个参数

其一:回话类型 converstationID: 聊天类型(如单聊C2C)${聊天对象id}

其二:下一次拉取消息列表时的消息id nextReqMessageID

其三:拉取数量上限 count

即时通讯登录sdk的tim实例下login方法,所需参数:用户id和用户签名

用户id指的是当时登录小程序的用户id

而用户签名则需要通过专门的获取签名函数来获取

D:\卓哥yyds\miniprogram-1\lib\tim\generate-test-usersig.js

D:\卓哥yyds\miniprogram-1\lib\tim\lib-generate-test-usersig.min.js

观察者模式

应用:全局状态管理

全局状态:被多个不同功能模块使用且使用方需要主动观察到其变化的数据

在页面中获取全局状态的语法

全局状态绑定工具tecent的Mobx,其createStoreBindings方法可以绑定自定义的全局状态,之后就可以this.data.xxx访问到全局状态属性了

全局store调用model方法,model再在类方法里面调用constructor里面tim实例的方法

在组件中获取全局状态的语法

通过behaviors配置引入,然后配置一个storeBindings对象为配置,在里面拿到全局状态就可以了

SDK IM实时通讯包 import TIM from 'tim-wx-sdk-ws'

两个tim文件的区别

model里的tim文件:为了限制不要重复创建SDK实例设置成一个类文件,在构造函数里面创建sdk实例,然后通过类方法用单例设计模式间接获得即可

store 全局状态仓库 用来存全局用到的,比如实时通讯的属性,方法等

组件高阶

定义组件间关系,形成组合组件

relations:{

        xxx组件路径:{

                type:'关系声明(child/parend)'

        }

}

注意:声明组件关系的组件是相互的,两个js文件都需要定义以上代码

还可以通过自定义组件给的方法getRelationNodes来获取子组件的数量

事件监听的冒泡

在父组件里实现对子组件的监听,然后在页面通过父组件拿到子组件的配置

子组件定义事件冒泡及穿透组件边缘为true

父组件定义监听事件,设置正常的事件触发,触发子组件的自定义事件

wxml   bind:子组件自定义的事件="处理函数"

js    处理函数 触发事件传递子组件的配置给页面即可   

云开发数据库事务

应用场景:跨集合且用到这些集合的功能有一致性要求时(比如签到成功则积分+5)

原子性介绍:要么全部成功要么全部失败

实物开始: db.runTransaction( async transaction => {执行的原子性函数})

注意:主函数之外的函数传入参数transaction后记得把db的普通操作改成transaction事务操作(增和改需要,查不需要) transaction.collection('xx').xxx()

事务机制 (其所有操作是对数据快照的操作,抛出异常之后则把快照撤销掉)

并发事务操作

小程序解决并发操作冲突:加事务锁,提交事务后再解锁

事务实践注意事项:

1.避免大事务

大事务的定义:跨多个集合或嵌套了耗时业务逻辑的事务;

2.一旦事务逻辑可以提前退出,技师提交事务或者触发回滚以释放锁

3.使用db.runTransaction()  原因:可以自动回滚事务和提交事务;冲突时自动重试3次

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值