小程序商城笔记

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   后端接口调试工具

https://www.getpostman.com/

 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 动态设置导航栏标题

https://developers.weixin.qq.com/miniprogram/dev/api/ui/navigation-bar/wx.setNavigationBarTitle.html?search-key=setNavigationBarTitle

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:

  1. 通过模板消息管理接口获取模板 ID(详见 模板消息管理
  2. 在微信公众平台手动配置获取模板 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)

posted @ 2018-07-21 22:50  zhaobao1830  阅读(1077)  评论(0编辑  收藏  举报