小程序商城笔记
1、三端分离:
服务端:主要是查询数据库,获取数据;
客户端:向服务端发送请求,完成自身逻辑;
CMS:向服务端发送请求,实现发货与发送微信信息。(CMS就是公司内部用户用的,主要功能是添加、修改商品这一类功能)
2、基于token管理权限:登录和有些用户有权限看什么,有些用户没有权限看什么。
3、
ORM模型(面向对象的模型),简单理解为:数据库中的一张表就是一个对象。关联模型就是多张表有关联,比如写sql语句的时候,多表关联
4、单元测试的作用:当业务代码复杂的时候,有可能会出现这种情况,刚修改一个地方的Bug,结果其他地方出问题了。要解决这种情况,就应该用单元测试
5、在GitHub上下载think-php
https://github.com/top-think/think 下载think-5.0.7 这个里面找到(相当于一个demo)
https://github.com/top-think/framework/tree/v5.0.7 下载ThinkPHP核心代码 framework-5.0.7
下载以后,把这俩个解压,把think-5.0.7解压,改名为项目名字,比如zerg,放在XAMPP下的htodcs文件夹下;把framework-5.0.7解压,改名为thinkphp放到zerg文件夹下,结构为:
6、下载XAMPP https://www.apachefriends.org/zh_cn/index.html
这个表示PHP的版本
点击这块,选择相应的php版本
7、微信里的登录、微信支付(预订单、库存量检测与回调通知处理(这是重点)、微信模板信息(非常重要,这是微信小程序唯一可以告诉用户的消息机制,模板信息是被动的,只有用户在小程序里触发了某些选项后,才有权利向用户发送这些消息,不能主动、随意地向用户推送消息))
8、Token令牌的存储:(1)、用后端语言自带的方法;(2)、写到一个配置文件里;(3)、存储到数据库里
9、
Web产品矩阵:
用一个技术把上面的这些产品都凝合起来,以实现更好的复用性,让整个架构变得合理和流畅。现在做web产品要有公共服务的概念。要有一个公共的api向这些产品提供共有的数据和服务
10、能写出代码和写出易维护的代码不是一回事
前端绝不等于做界面和特效,前端与服务器在编程思维上的差异越来越小了
前端已经变得和服务器一样需要处理大量的业务逻辑
11、第三方组件应该合理选择:
(1)、第三方组件封装的层次不一样,有时候引入第三方组件会引发代码bug
(2)、很多功能我们用不上,要浪费很多时间去学习第三方组件,并不比我们自己实现功能消耗的时间短
(3)、第三方组件的一些功能与我们自己所要求的功能有冲突,要花很多时间去处理
(4)、第三方组件会侵入我们自己的代码
(5)、用第三方组件,不利于提高自己的逻辑能力和开发能力
(6)、有一些复杂的功能,比如访问数据库,自己写不出来,或者写出来的效用不好,就可以使用第三方组件库
(7)、有的第三方组件库没有侵入自己的代码,只是作为一个类库来使用,这样的第三方组件库可以使用
12、
vendor:第三方的插件就安装到这里
thinpphp:tp5的核心代码,用来支持框架的运行
runtime:运行文件、日志文件就放在runtime里
public:外部站点的目录,这里面的文件,可以被直接访问到
extend:之前已经写好的第三方类库,放入这个里面的类库,命名空间是可以被框架自动注册的
application:核心代码
13、tp5自带的web服务器:配置PHP环境变量,把D:\xampp\php(php.exe)添加到PATH里面,cmd进入public文件夹,运行php -S localhost:8080 router.php
在浏览器中输入localhost:8080
这个只是本地测试用,最好还是用xampp
14。URL路径格式
说明:蓝色的:域名
index.php 入口文件,PHP默认的
绿色index:模块名(项目中会有多个模块)
紫色index:controller名
棕色Index:controller下面的文件
对比下面的结构
15、创建class的时候,如何自动匹配命名空间
config.php里定义的命名空间,默认为app,可以修改
使用PhpStrom配置,setting-->Directories ,选中application,点击Sources,,然后点击右下角的,设置为app
实战经验:php中,模块的范围大,中小型的项目,单一模块就够了,不要一个功能一个模块
16、虚拟域名的配置
现在启动项目,如果要访问
Url为:http://localhost/zerg/public/index.php/sample/test/hello
效果为:
这样的话太长了
现在起个虚拟域名:z.cn
点击xampp里的
找到D:\xampp\apache\conf\extra下的httpd-vhosts.conf文件,在最下面加入如下代码:
1 <VirtualHost *:80> 2 DocumentRoot "D:\xampp\htdocs\zerg\public" 3 ServerName z.cn 4 </VirtualHost>
在C:\Windows\System32\drivers\etc下找到hosts文件,最下面加入如下代码:
1 127.0.0.1 z.cn
重新启动Apache
输入url:http://z.cn/sample/test/hello
显示效果为:
PhpStrom 断点调试:https://coding.imooc.com/lesson/97.html#mid=3320
在项目的public下面创建一个文件infor.php
输入phpinfo();
在浏览器打开 localhost/zerg(项目名)/public/infor.php(我配置了虚拟域名,所以打开的Url 是:http://z.cn/infor.php)
在打开的页面里搜索Xdebug,如果有就说明安装成功了,如果没有,就说明没有安装
安装一个Xdebug 网站是:https://xdebug.org/download.php
在刚才Infor的页面,查找源代码,然后复制,粘贴到下面的框里
这样就会出现与本地使用的php相匹配的Xdebug,不过7以下的不行
链接:https://pan.baidu.com/s/1O3tdu0rz0hA_bBC2YY3xhA
提取码:zhwo
这个里面有
下载好文件后,
找到这个路径D:\xampp\php\ext,把刚才的文件放进去
点击
打开php.ini,把下面的代码复制到最下面
[Xdebug] zend_extension = D:\xampp\php\ext\php_xdebug-2.2.5-5.6-vc11.dll (这个路径根据你自己的来) xdebug.remote_enable=1 xdebug.remote_handler=dbgp xdebug.remote_mode=req xdebug.remote_host=localhost xdebug.remote_port=9000 xdebug.idekey="PHPSTORM"
重启
刷新infor页面,查找Xdebug,如果有,说明安装成功
现在开始配置调试
点击
配置服务器
点击下面的启动调试
把这个复制到postman的接口后面,请求的时候,就可以开启调试
17、Postman 后端接口调试工具
18、ThinkPHP5中支持三种路由:
(1)、默认的,PATH_INFO:
1 //配置式路由 2 return [ 3 '__pattern__' => [ 4 'name' => '\w+', 5 ], 6 '[hello]' => [ 7 ':id' => ['index/hello', ['method' => 'get'], ['id' => '\d+']], 8 ':name' => ['index/hello', ['method' => 'post']], 9 ], 10 11 ];
(2)、强制路由(最标准的,项目中推荐用这种)
开启强制路由:在application/config.php中,,值改为true
1 //动态路由 2 use think\Route; 3 4 Route::rule('hello', 'sample/Test/hello');
标准路由的俩种写法:
1 //(1)、第一种写法 2 Route::rule('hello', 'sample/Test/hello', 'GET', ['https'=>true]); 3 Route::rule('hello', 'sample/Test/hello', 'GET|POST', ['https'=>true]); 4 //(2)、第二种写法 5 Route::get('hello', 'sample/Test/hello'); 6 Route::post(); 7 Route::any();
(3)、混合模式
就是上面俩种都可以用
19、路由参数 https://coding.imooc.com/lesson/97.html#mid=3338
20、验证器 https://coding.imooc.com/lesson/97.html#mid=3351
21、REST之前的重要协议是SOAP,重,使用XML描述数据
REST是用JSON描述数据
XML和JSON都是通用的,与语言无关,可以在不同的语言之间交换数据
REST的出现,更多的是给我提供了一种轻量级的思维方式,前端可以通过javascript直接访问后台
22、REST是一种思想,RESTFuL API 是基于REST的API的设计理论
无状态:假如发生了俩个http请求,这俩个Http请求之间是没有先后顺序的,也没有直接的关系,第二个请求是不需要依赖第一个请求的。
比如我们在访问数据库的时候,是要链接和打开数据库的,只有这个成功了,才能去做一些对数据库的操作,删除和增加,完成后要记得把这个链接close掉,这就不是无状态的,必须有个前置操作。
RESTFUL 请求就没有这些
备注:传统开发中的GET、POST和RESTFUL中的GET、POST,用法没有区别,但是意义上区别很大
在传统开发中,选择GET、POST的依据是:如果传输的数据简单,不需要保密,就用GET,否则就用POST
在RESTFUL中,选择GET还是POST,是看对资源是做什么操作,如果是获取资源,就用GET,如果是创建资源,就用POST
404:找不到页面
400:请求参数错误
401:没有权限访问
403:当前的资源被禁止。有权限访问,但是因为某些原因,资源被禁止
例子:有俩个用户请求数据,A用户请求的时候传递的是B用户的ID,这时候就应该返回403
500:服务器的未知错误,(1)、确实不知道哪里错了,无法返回具体的错误提示,所以就返回500;(2)、知道哪里错误了,但是这是我服务器的原因,与你客户端无关,不想让客户端知道服务器出了什么问题,返回500
豆瓣的简单,GitHub的标准 https://developer.github.com/v3/
完全按照标准REST不容易,尤其是在内部开发中,比如查询,参数不同,如果做成给一个接口,要各种判断,代码会非常复杂
23、什么时候用全局异常:(1)、每级要处理上级的异常,很繁琐,也有可能没有捕获,(2)、有些异常没有预料到,没有捕获。需要一个全局异常,做出统一的处理
此外很多框架中已经有了全局异常,比如thinkphp5,这时候就需要我们重写这个错误
23、thinkphp里的数据库三种操作方法:
(1)、原生SQL
1 Db::query('select * from banner_item where banner_id=?',[$id]);
24、详细:https://coding.imooc.com/lesson/97.html#mid=3576
项目运行中发现一个问题,当url错误的时候,会报错:httpException不是Exception,经过调试发现,httpException继承的是\RuntimeException,不是Exception的子类
25、连接数据库的原理
如果是直接用sql连接数据库,那就是用Collection连接
如果用的是Query查询,就是先用Builder(生成器)编译成SQL,再传给Collertion
在TP5中,不是直接访问数据库,是通过一个中间层来操作数据库,就是dal,好处:(1)、简化sql代码的编写;(2)、不需要关心具体的实现,只要同意使用中间层提供的db类,就可以访问不同的数据库
db的原理:它是一个工厂模式,使用的时候,db根据不同的配置文件,来调用不同的驱动,这个驱动才是真正决定Collection是什么类型的
27、开启SQL日志记录 https://coding.imooc.com/lesson/97.html#mid=3591
index.php是入口文件,每一个url请求过来,都会经过这个文件,所以可以在这个文件进行配置
28、https://coding.imooc.com/lesson/97.html#mid=3610
ORM Object Relational Mapping 对象关系映射 设计表的时候,要当成对象来设计,操作的时候,不是在操作表,而是在操作一个个对象
在tp5中,模型不只是一张表,更是一个业务逻辑,当业务逻辑简单时,模型可以是一张表,但是复杂时,是多张表的联合
29、Db是一个数据库访问层,model是建立在Db访问层上的更加抽象的一个处理业务逻辑的模型层
30、thinkPhp5里类和模型的区别,类是一个抽象的,模型是具体的(类似于java里的对象)
thinkPhp5调用模型的方法有俩种:静态调用(推荐)和实例对象调用。这个和Java里面不一样,Java都是new 一个实例对象后,调用里面的方法
为什么不推荐用实例对象调用呢?
https://coding.imooc.com/lesson/97.html#mid=3655
逻辑上的问题:实例化对象后,模型对象对应数据库里的一条数据,一条数据get一个id,这个说不过去
面向对象中,类和对象的区别,model里面,一个类对应的是数据库的一张表,而一个new出来的对象,对应的是表里的一条数据
31、查询数据的时候,隐藏某些字段 https://coding.imooc.com/lesson/97.html#mid=3909
32、tp5里公开的配置项文件是extra,在这个文件添加文件(这个里面可以自定义一些配置,下面的这个表示返回的图片路径前面加上http://z.cn/image)
调用的时候
config('setting.img_prefix')
33、在TP5里面,如果出现router前面类似的,就需要开启完整路由匹配
在config.php里面
改为true
33、8.16数据库字段冗余的合理利用(合理的)
在设计数据库的时候,可以适当的冗余,举个例子:product表关联的image表,我们要获取img的url,就需要查询imgage表,如果product表数量很多的话,速度会变慢,有一种优化的方法,把url存在product里面,这样只要查询image表就可以,不用再查询image表了
39、8-19
如果想在某个方法里隐藏某个字段,可以使用TP5框架里的collection,它可以把数据转换成一个对象,这样就可以使用里面的方法hidden来进行隐藏字段
1 $collection = collection($products); 2 $products = $collection->hidden(['summary']);
在thinkphp5中,直接修改database里的
// 数据集返回类型
'resultset_type' => 'collection'
这样就可以让返回的数据为collection对象
TP5中,判断对象为空,可以使用isEmpty()方法
40. 9-1 token
验证token:(1)、验证这个token在数据库里;(2)、这个token没有过期;(3)、如果token在数据库里,而且没有过期,还要验证这个token所在的分组有权限调用这个接口
41、9-2微信身份体系设计
在小程序中,我们是基于微信体系做的,所以登录的时候不需要输入账号和密码
小程序把code码发送给getToken接口,getToken接口接收到code码以后,会向微信服务器发送一个请求,把code码传递到微信服务器,微信服务器接收到code码以后,会返还openid(用户身份的标识)和session_key
session_key的作用:在微信体系中,可以直接访问微信服务器拿到一个加密信息,要想解密这个信息,就需要session_key
加密信息里面包含一个UnionID(也是用户的标识)
UnionID和openid的区别:
openid是一个用户针对一个小程序,它有一个openid,一个用户在不同的小程序中,openid是不同的
UnionID在不同的小程序下是相同的,只要是同一个账号注册的小程序、公众号、服务号,都是相同的
从微信服务器获取到openid后,把它存储到服务器中,生成token,然后返回给小程序端
我们可以把token保存到缓存中,因为我们有可能会遇到这种情况,打开一个页面,就需要请求一次服务器,获取token,验证token是否有效,如果把token保存到缓存中,就可以在缓存中获取token进行验证,减少服务器压力
备注:缓存的维护不容易,选取技术的时候,要慎重,既要考虑到优点,还要考虑到缺点
42、 9-11 闭包函数构建查询器
要求:关联俩张表查询数据,根据imgs表里的order字段进行排序,经过演变后,使用了下面的写法(多看)
model/Product.php
1 public static function getProductDetail($id) 2 { 3 $product = self::with([ 4 'imgs' => function($query){ 5 $query->with(['imgUrl']) 6 // order('order', 'asc') 第一个order是排序,第二个order是数据库里的字段 7 ->order('order', 'asc'); 8 } 9 ]) 10 ->with(['properties']) 11 ->find($id); 12 return $product; 13 }
43、9-12 通过令牌获取用户标识
令牌Token是用户访问受保护的接口的必须参数
为什么不直接传递UID,而是通过令牌获取UID?
uid是自增长生成的,容易被别人猜到
使用令牌获取UID的好处是:在post提交的时候,如果提交的是俩个用户,令牌是A用户的,UID是B用户的,这样修改的地址就是B用户的,容易出错
44、9-15 参数过滤
Controller/Address.php
1 // 根据规则取字段是很有必要的,防止恶意更新非客户端字段 2 $data = $validate->getDataByRule(input('post.'));
getDataByRule 这个方法是用来过滤客户端传回的参数的,uid我们是用token获取的,但是为了怕客户端传过来uid,覆盖token获取的uid,所以我们要过滤参数
45、10-1 Scope权限作用域
用来判断用户的权限,可以先创建一个配置文件,在里面配置好几种权限,然后代码里用到什么就调用
47、前置方法
就是请求接口时,先执行这个方法
48、小程序下单支付流程
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3
小程序调用下单API,检查库存,如果有库存,就下单成功;下单成功后,调用支付API,我们自己的服务器调用微信服务器,生成预订单,返回支付参数,然后把支付参数传给小程序,小程序拿到支付参数后,就调用相应的接口,请求微信,进行支付,弹出支付窗口。支付成功或失败后,一方面返回给小程序提示信息,另一方面返回给我们的服务器信息(异步的,会在一定时间内多次推送)
49、10-10 订单快照
订单快照 保存的信息是当时下单时候的信息,地址和商品价格、数量,一般都是通过商品ID查询获取商品信息,这样不好,因为商品的名称和价格有可能改变,这样获取的数据和当时下单的时候的数据不一样,解决办法是下单的时候,就把订单里的商品信息都保存在订单order表里
50、TP5自动写入时间戳
在表里面,经常有create_time,update_time,delete_time这些属性,如果我们不想在保存数据的时候手动加入,可以在对应的mode里面写入如下代码,当保存数据的时候,自动加入当前时间
1 protected $autoWriteTimestamp = true; //自动返回当前时间戳
什么时候TP5会给create_time自动加入时间,当检测到新加一条数据的时候
同样,如果做的是删除操作的时候,会自动给delete_time自动加入时间
这里特别说明下delete_time这个,现在我们很多时候删除数据,并不是真实的删除,而是假删除,只要delete_time有值,就表示这条数据被删除了
记住:要使用TP5自动写入时间戳,必须用模型的方式,如果用原生SQL,是不行的
如何自定义TO5里的create_time,update_time,delete_time这些名称
51、TP5中使用事务
遇到下面的问题
我们执行一个方法的时候,在俩个表里保存相关的数据,如果只保存了前面的数据,后面的没有保存成功,这样会出问题,这里用到的数据库中的事务
在TP5中。要解决这个问题,就需要下面的代码
Db::startTrans(); Db::commit();
1 Db::startTrans(); 2 try{ 3 $orderNo = $this->makeOrderNo(); 4 $order = new \app\api\model\Order(); 5 $order->user_id = $this->uid; 6 $order->order_no = $orderNo; 7 $order->total_price = $snap['orderPrice']; 8 $order->total_count = $snap['totalCount']; 9 $order->snap_img = $snap['snapImg']; 10 $order->snap_name = $snap['snapName']; 11 $order->snap_address = $snap['snapAddress']; 12 $order->snap_items = json_encode($snap['pStatus']); 13 14 $order->save(); 15 16 $orderID = $order->id; 17 $create_time = $order->create_time; 18 19 foreach ($this->oProducts as &$p){ 20 $p['order_id'] = $orderID; 21 } 22 $orderProduct = new OrderProduct(); 23 $orderProduct->saveAll($this->oProducts); 24 Db::commit(); 25 return [ 26 'order_no' => $orderNo, 27 'order_id' => $orderID, 28 'create_time' => $create_time 29 ]; 30 }catch (Exception $ex){ 31 Db::rollback(); 32 throw $ex; 33 }
52、微信支付SDK
分为俩端的,客户端和服务端
客户端:在百度搜索微信支付开发者文档
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1
服务端:在百度搜索微信支付开发者文档
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
53、 10-21
下载PHP版的SDK,解压,在extend下创建个文件夹,把lib里的复制到里面
54、在TP5中,引入extend里的文件
55、 10-18
生成一个微信服务器需要的订单,不是我们真正的订单,用预订单,是为了从微信服务器返回支付参数
56、小程序业务流程
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_4&index=3
57、微信支付 签名 10-26
https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html
签名的作用:为了保证传送的数据不被修改(当然,这是相对的,不能保证一定不被修改)
举例说明签名的作用:服务端有三个参数:A。B、C,现在用这个三个参数和APPKey四个参数一起,使用MD5,做成Sign签名,然后传送给客户端,客户端又传送到微信服务端,
微信服务端用同样的规则把传过来的参数和APPKey生成Sign签名,进行验证,俩个签名是不是一样,如果一样,就说明传送过来的参数正确
58、10-29 支付回调通知处理
1 // 微信支付回调处理 2 public function receiveNotify(){ 3 //通知频率为15/15/30/180/1800/1800/1800/3600,单位:秒 4 5 //1.检查库存量,有可能超卖 6 //2.更新这个订单的status状态 7 //3.减库存 8 //如果成功处理,返回微信成功处理信息,否则返回未成功处理信息 9 10 //微信返回的数据特点:post,xml格式,不会携带参数 11 // 使用SDK的好处 可以处理XML格式 12 }
微信支付成以后,会调用一个接口,返回处理的信息,这个接口需要我们自己定义receiveNotify()
备注:这个接口必须是post请求,返回的格式是xml,而且不会再里面携带参数(类似url?xx=xx这种)
我们用了SDK,可以很容易的处理XML数据
要覆盖WxPay.Notify.php里的NotifyProcess方法
59、10-30 支付回调通知
$data的说明 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8
确定是否成功,要看下面这个字段
60、把本地服务转换成外网,可以使用类似ngrok,不过这种工具,一般不安全
61、使用了代理以后,secure.php里pay_back_url要重新配置,具体看 10-23
62、10-34 可以断点调试微信支付的回调吗?
正常情况,微信支付后,会自己调用我们提供的接口,这时我们是无法断点调试接口信息的
有一个方法:新创建一个方法,微信服务器调用的方法里面调这个方法,在这个方法里面断点调试微信服务器返回的信息
63、10-37
要把返回的数据里的某个字段进行json格式化处理,可以在Model里定义读取器
微信端
64、11-3
微信小程序在真机上运行时要提前配置域名
进入小程序后台管理界面 https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=726946140&lang=zh_CN
只是请求的话只需要配置 request合法域名
65、11-4 异步回调和箭头函数
https://www.cnblogs.com/zhaobao1830/p/9804499.html
66、11-6
1 // if(params.sCallBack){ 2 // params.sCallBack(res); 3 // } 4 // 这俩种写法是一样的 推荐用下面的,微信的demo中就这样写的 5 params.sCallBack && params.sCallBack(res.data);
67、小程序模板template的一些注意
父文件:
1 <!--引入template文件--> 2 <import src="../tpls/products/products-tpl.wxml" /> 3 4 <!--使用data把数据传递到template里面--> 5 <template is="products" data="{{products:productsArr}}"></template>
模板文件:
1 <template name="products"> 2 <view class="products-box"> 3 <block wx:for="{{products}}"> 4 <view class="products-item"> 5 <image class="products-image" src="{{item.main_img_url}}"></image> 6 <view class="products-item-bottom"> 7 <text class="name">{{item.name}}</text> 8 <view class="price">¥{{item.price}}</view> 9 </view> 10 </view> 11 </block> 12 </view> 13 </template>
(1)、父文件要引入模板文件的路径
(2)、父文件里的is和模板文件里的name一致
(3)、模板文件里不进行js操作,需要的数据是由父文件里传过来的,使用 data={}
(4)、模板文件的样式,在父文件的样式里引入
1 @import "../tpls/products/products-tpl.wxss";
67、底部的配置
1 "tabBar": { 2 "list": [ 3 { 4 "pagePath": "pages/home/home", 5 "text": "首页", 6 "iconPath": "imgs/toolbar/home.png", 7 "selectedIconPath": "imgs/toolbar/home@selected.png" 8 }, 9 { 10 "pagePath": "pages/category/category", 11 "iconPath": "imgs/toolbar/category.png", 12 "selectedIconPath": "imgs/toolbar/category@selected.png", 13 "text": "分类" 14 }, 15 { 16 "pagePath": "pages/cart/cart", 17 "iconPath": "imgs/toolbar/cart.png", 18 "selectedIconPath": "imgs/toolbar/cart@selected.png", 19 "text": "购物车" 20 }, 21 { 22 "pagePath": "pages/my/my", 23 "iconPath": "imgs/toolbar/my.png", 24 "selectedIconPath": "imgs/toolbar/my@selected.png", 25 "text": "我的" 26 } 27 ], 28 "borderStyle": "white", // 边框的颜色 29 "selectedColor": "#AB956D", //选中以后文字的颜色 30 "color": "#989898", // 未选中文字的颜色 31 "backgroundColor": "#F5F5F5" // 背景颜色 32 }
68、调试技巧
引入template的时候,不显示:在template里面随便打一行字,如果显示,就说么是数据的问题,如果不显示,就说明模板没有引入,这时候就要检查俩个地方:
(1)、在父组件里,有没有用inport引入模板文件
(2)、父组件传入的数据key和模板里的是否一致
在微信开发工具里,AppData里可以查看当前页面里的数据
69、11-16 动态设置导航栏标题
wx.setNavigationBarTitle(Object object)
注意:1、要在onReady里面调用,在onLoad里调用的时候,有可能会失效 2、全局设置导航栏标题的的地方必须为空,否则有可能先显示全局设置的,然后显示动态设置的,会闪一下
70、11-18 Picker组件
https://developers.weixin.qq.com/miniprogram/dev/component/picker.html
1 <picker class="" range="{{countsArray}}" bindchange="bindPickerChange" value="1"> 2 <!--flex--> 3 <view> 4 <text class="counts-tips">数量</text> 5 <text class="counts-data">{{productCount}}</text> 6 <image class="counts-icon" src="../../imgs/icon/arrow@down.png"></image> 7 </view> 8 </picker>
picker对flex的支出不是很好,所以为了让picker里面的值都在中间,可以在他们外面包裹一个view,view源码里用的是flex布局
71、11-23 微信小程序数据从服务器端到前端的流程
页面初始化时,JS层调用API,从服务器端获取数据,然后进行数据绑定,在wxml显示数据。
前端有时候会进行操作,通过标签的自定义属性(data-)把参数传递到js层,js层用event获取,然后把参数通过API传递到服务器端,服务器端响应后把心得数据
再传递到J层,然后进行新的数据绑定
在小程序中,数据绑定是最重要的部分,类似的有angular,js和vue.js
72、编译设置
每次我们改变代码的时候,都会跳转到第一页,可以这样设置
这样就会跳转到指定页面
73、12-4
1 for (let i = 0; i < len; i++) { 2 //避免 0.05 + 0.01 = 0.060 000 000 000 000 005 的问题,乘以 100 *100 3 if (data[i].selectStatus) { 4 account += 5 data[i].counts * multiple * Number(data[i].price) * multiple; 6 selectedCounts += data[i].counts; 7 selectedTypeCounts++; 8 } 9 }
注意这种写法,在Js里,小数相乘会出现特别的结果,可以先乘以10的幂数,把值变成整数再相乘,最后对结果进行处理
74、12-5 购物车页面开发
不需要在页面显示,可以是用block,类似于大括号。
wx:if和wx:else不一定非要俩个相似的标签
75、跳转到tab栏下面的页面,必须使用switchTab
76、13-4 客户端令牌管理机制
程序初始化的时候,先从缓存(Storage)中读取令牌,检测令牌,如果令牌失效或者不存在,则请求token,把获取到的令牌保存到缓存(token)中
model(泛指所有向后端发送请求的文件)中请求后端API的时候,携带令牌去请求
如果在初始化的时候有令牌,在请求API的时候却没有,返回401,那就重新请求令牌,然后携带令牌去请求API
75、13-17 获取用户信息
1 wx.login({ 2 success: function () { 3 4 wx.getUserInfo({ 5 6 success: function (res) { 7 typeof cb == "function" && cb(res.userInfo); 8 }, 9 10 fail: function (res) { 11 typeof cb == "function" && cb({ 12 avatarUrl: '../../imgs/icon/user@default.png', 13 nickName: '零食小贩' 14 }); 15 } 16 17 }); 18 }, 19 20 })
备注:wx.login获取code,进而获取poenid,是不需要授权的
wx.getUserInfo是需要授权的
76、13-17 获取用户信息
在小程序里面,最好不要在页面中间自定义Loding组件,体验效果不好;如果特别需要,可以在顶部定义一个
77、wx.getUserInfo 获取用户信息
调用这个接口前,会让用户授权,如果是同意,可成功获取用户信息;如果是不同意,那将进入fail回调,而且不会再出现授权页面
78、13-20
合并俩个数组
1 this.data.orderArr.push.apply(this.data.orderArr, data);
79、13-20
onReachBottom 是Page的事件,页面滚动到最底部的时候触发
scroll-view组件也有这种效果,不过如果需要js控制好,那么推荐用onReachBottom
80、微信模板信息 14章的总结
微信模板信息链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/template-message.html
看使用说明:
步骤一:获取模板 ID
有两个方法可以获取模板 ID:
- 通过模板消息管理接口获取模板 ID(详见 模板消息管理)
- 在微信公众平台手动配置获取模板 ID
登录 https://mp.weixin.qq.com 获取模板,如果没有合适的模板,可以申请添加新模板,审核通过后可使用,详见 模板审核说明
要想使用模板信息,需要先在https://mp.weixin.qq.com 这个里面选择需要的模板
点击添加按钮进行添加
添加完以后,记住 模板ID,请求模板信息接口的时候,要用这个ID(对应的参数是template_id)
步骤二:页面的 <form/>
组件,属性 report-submit
为 true
时,可以声明为需要发送模板消息,此时点击按钮提交表单可以获取 formId
,用于发送模板消息。或者当用户完成 支付行为,可以获取 prepay_id
用于发送模板消息。
有俩种发送模板信息的情况,一种是使用form组件,一种是支付完成后发送
现在讨论支付完成这种情况,注意prepay_id
,这也是参数之一,对应的参数是form_id
步骤三:调用接口下发模板消息(详见 sendTemplateMessage )
通过上面俩个步骤,获取了template_id和form_id,再加上其他参数,就可以请求接口了
现在我们来看https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html,分析发送模板信息接口
参数分析
string access_token 小程序全局唯一后台接口调用凭据
具体信息,查看 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/access-token/getAccessToken.html
string touser 接收者(用户)的 openid
string template_id 所需下发的模板消息的id 上面已经说了
string page 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
string form_id 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id
string data 模板内容,不填则下发空模板
string emphasis_keyword 模板需要放大的关键词,不填则默认无放大
请求数据实例
1 { 2 "touser": "OPENID", 3 "template_id": "TEMPLATE_ID", 4 "page": "index", 5 "form_id": "FORMID", 6 "data": { 7 "keyword1": { 8 "value": "339208499" 9 }, 10 "keyword2": { 11 "value": "2015年01月05日 12:30" 12 }, 13 "keyword3": { 14 "value": "腾讯微信总部" 15 } , 16 "keyword4": { 17 "value": "广州市海珠区新港中路397号" 18 } 19 }, 20 "emphasis_keyword": "keyword1.DATA" 21 }
81、15-2 另一种思路处理库存量的问题
之前是先创建订单,在支付以后在数据库里扣除数量;
新的思路是在创建订单后,就暂时扣除数量,支付以后,就正式扣除数量,如果在一段时间就没有支付,就恢复数量
难点是:如何控制,没有支付就恢复数量,可以使用定时器(不是很好),队列(类似于redis)