为了账号安全,请及时绑定邮箱和手机立即绑定
3.1 微信小程序 API

uni-app 的 API 与微信小程序 API 基本一致。掌握微信小程序 API 对后面的开发很有帮助。微信小程序 API 文档:https://developers.weixin.qq.com/miniprogram/dev/api/

3.1 打包为微信小程序

注册微信小程序账号,获取到 AppID,我们后面配置的时候会用到。在 HBuilderX 工具栏,点击发行,选择小程序-微信。输入小程序名称和 AppID,单击发行就可以了。这样我们就会获得一个微信小程序的打包文件,接下来我们来发布微信小程序项目,打开微信小程序开发者工具,导入刚刚生成的微信小程序项目的打包文件,在微信小程序开发者工具中先测试一下,项目运行是否正常,项目测试没有问题后,点击右上角>>按钮,上传代码就可以发布微信小程序了,最后等待微信团队审核通过,别人就可以在线上访问到你的项目了。

5.6 在商品页面通过模板引擎规则显示商品信息

此时我们可以根据 FreeMarker 模板引擎,按模板规则显示商品信息了。实例:<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>商品列表</title></head><body><div>商品列表:</div><#list goodsList as item>${item.name}--${item.price}--${item.pic}</#list></body></html>注意我们通过 FreeMarker 的模板语法,输出了商品列表信息。关于 FreeMarker 模板引擎更多的语法规则,感兴趣的同学可以后续查阅更多资料。

2. 正则表达式规则

Tips: 正则表达式= 特殊字符(元字符) + 文本(普通字符)上面的公式其实就是一个完整的正则表达式,你可以简单的将正则表达式理解为是一种语言,元字符就是它的语法,普通字符就是单词。我们来看一个简单的正则表达式的例子:下面是一个自动化配置 terraform 的一个配置文件 main.tf。我们会用正则表达式 grep -E ‘(image_id|key name)’ main.tf 来同时匹配这两个字段。对于不太了解正则表达式的人来说这段简单的公式是有点云里雾里的。下面我们来具体看下正则表达式具体语法规则有哪些,然后再回过头来看就一目了然了。

6.6 在商品页面通过模板引擎规则显示商品信息

此时我们可以根据 Thymeleaf 模板引擎,按模板规则显示商品信息了。实例:<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>商品列表</title></head><body> <div>商品列表:</div> <div th:each="item:${goodsList}"> <span th:text="${item.name}"></span> <span th:text="${item.price}"></span> <span th:text="${item.pic}"></span> </div></body></html>注意我们通过 Thymeleaf 的模板语法,输出了商品列表信息。关于 Thymeleaf 模板引擎更多的语法规则,感兴趣的同学可以后续查阅更多资料。

7.6 在商品页面通过模板引擎规则显示商品信息

此时我们可以根据 JSP 模板引擎,按模板规则显示商品信息了。实例:<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>商品列表</title></head><body> <div>商品列表:</div> <c:forEach var="item" items="${goodsList}"> ${item.name}--${item.price}--${item.pic} </c:forEach></body></html>注意我们通过 JSP 的模板语法,输出了商品列表信息。关于 JSP 模板引擎更多的语法规则,感兴趣的同学可以后续查阅更多资料。

动态规划算法介绍

今天我们来介绍基础算法中非常重要而且又略微烧脑的算法:动态规划 (Dynamic Programming, 简称DP) 算法。

4. 乐观锁

乐观是一种积极的解决问题的态度。所谓乐观锁认为系统中的事务并发更新不会很频繁,即使冲突了也没事,大不了重新再来一次。基本思想:每次提交一个事务更新时,查看要修改的数据从上次读取以后有没有被其它事务修改过,如果修改过,那么更新就会失败。实现方案:在实体中增加一个版本控制字段,每次事务更新后就将版本 (Version) 字段的值加 1。Tips: 乐观锁本质就是版本控制管理的实现,记录的每一次更新操作都会以版本递增的方式进行记录。一个事务在更新之前,先获取记录的当前版本号,更新时,如果版本还是最新的则可以更新,否则说明有事务比你先更新,则需要放弃。或者重新查询到最新版本信息后再更新。所以,在乐观锁的实现中,冲突是常态。实现过程:在学生实体类中添加新属性,用来记录每次更新的版本号。public class Student implements Serializable {//省略…… @Versionprivate Long version;//省略…… }stu = (Student) session.get(Student.class, new Integer(1));System.out.println("当前版本号:"+stu.getVersion);//模拟延迟,如果在这个时间内有其它事务进行了更新操作,此事务的更新不会成功Thread.sleep(30000);stu.setStuName("Hibernate");transaction.commit();好了,悲观也好,乐观也好,只是一种解决问题的态度。对于这两种态度,咱们要总结一下。乐观锁:优势:性能好,并发性高。缺点:用户体验不好,可能会出现高高兴兴去更新,却告知已经有人捷足先登了。悲观锁:优势:锁住记录为我所用,没修改完成之前,其他事务只能瞪眼瞧着,时间虽然延迟,至少心里有底。缺点:并发性不好,性能不高。Hibernate 的其它性能优化:随时使用 Session.clear()及时清除 Session 缓存区的内容;1+N 问题 ( 一条 SQL 语句能解决的问题用了很多条 SQL 语句来实现) ;使用 Criteria 查询可以解决这个问题;Lazy 加载:需要时,使用 get() 方法发出 SQL 语句。使用类似于 from Student s left join s.classRoom c 的关联查询语句。缓存使用:在对象更新、删除、添加相对于查询要少得多时, 二级缓存的应用将不怕 n+1 问题,因为即使第一次查询很慢,之后直接缓存命中也是很快的,刚好又利用了 n+1。

2.3 广播的规则

所以根据上述案例,可以把广播规则简单总结如下:让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐;输出数组的形状是输入数组形状的各个维度上的最大值;如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错;当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。

3.2 灵活的规则配置

在我们使用 Swagger Codegen 进行代码生成操作时,我们需要对生成的代码进行统一的规定,在规定完之后,Swagger Codegen 即可为我们生成符合我们要求的代码,而且每一个类都是符合规范的。这就表明,我们可以在代码生成前灵活的对代码生成规则进行配置,这就使得在最终生成的代码中,我们不用再为代码规范所发愁,不用专门的去修改项目中不符合规范的代码了。

3.3 方法重写规则

关于方法重写,有以下规则:重写方法的参数列表应该与原方法完全相同;返回值类型应该和原方法的返回值类型一样或者是它在父类定义时的子类型;重写方法访问级别限制不能比原方法高。例如:如果父类方法声明为公有的,那么子类中的重写方法不能是私有的或是保护的。具体限制级别参考访问修饰符;只有被子类继承时,方法才能被重写;方法定义为 final,将不能被重写(final 关键字将在本节后面讲到);一个方法被定义为 static,将使其不能被重写,但是可以重新声明;一个方法不能被继承,那么也不能被重写;和父类在一个包中的子类能够重写任何没有被声明为 private 和 final 的父类方法;和父类不在同一个包中的子类只能重写 non-final 方法或被声明为 public 或 protected 的方法;一个重写方法能够抛出任何运行时异常,不管被重写方法是否抛出异常。然而重写方法不应该抛出比被重写方法声明的更新更广泛的已检查异常。重写方法能够抛出比被重写方法更窄或更少的异常;构造方法不能重写。

1.变量规则

这里以之前获取学生列表接口为例,若要在路由层面增加变量的过滤规则,可以使用pattern 方法,如下://获取学生列表接口Route::get('students/:name', 'app\controller\Study\StudentController@getStudents')->pattern(['name' => '[\w|\-]+']);如下图所示:Tips: 其中 :name 表示路由后面可以跟变量 name,[\w|\-]+ 是一个正则表达式,对 name 字段匹配。下面在 getStudents 方法中打印 name 变量,并返回正确的请求结果:/** * 获取学生列表 * @return \think\response\Json * @throws \think\db\exception\DbException */ public function getStudents() { halt($this->request->param('name')); //每页条数 $size = (int)$this->request->param('size', 15); $students = StudentModel::where('status', 1)->order('created_at DESC')->paginate($size); return json($students); }如下图所示:请求正确结果如下图:请求不满足正则匹配的要求如下图:

3.3. 乐观读模式

这是一种优化的读模式。乐观读模式相关的几个方法如下。tryOptimisticRead () 方法:非阻塞尝试乐观获取读锁,只有当写锁没有被获取时返回一个非 0 的 stamp 。乐观读取模式适用于短时间读取操作,降低竞争和提高吞吐量。在使用时一般需将数据存储到一个副本中,在后继处理中用于对比数据是否是最新状态;validate (long stamp) 方法:用于检查在获取到读锁 stamp 后,锁有没被其他写线程抢占。如果写锁没有被获取,那么 validate () 方法返回 true。可多次调用验证这一信息。另外,此类也提供了一组读写锁之间的转换方法:tryConvertToWriteLock (long stamp) 方法:尝试转换为写锁。转换条件:tryConvertToReadLock (long stamp) 方法:尝试转换为悲观读锁。tryConvertToOptimisticRead (long stamp) 方法:尝试转换为乐观读锁。注意此类的编程方法有这样一个共通特征:所有获取锁的方法,都返回一个邮戳(Stamp),Stamp 为 0 表示获取失败,其余都表示成功;所有释放锁的方法,都需要一个邮戳(Stamp),这个 Stamp 必须是和成功获取锁时得到的 Stamp 一致;下面我们举一个具体的编程例子。

1. 爬虫简介

网络爬虫,又称为网页蜘蛛,是一种按照一定的规则、自动地抓取万维网信息的程序。爬虫是一个自动下载网页的程序,它有选择的访问万维网上的网页与相关的链接,获取所需要的信息。爬虫有着广泛的应用:搜索引擎,谷歌百度等搜索引擎使用爬虫抓取网站的页面舆情分析与数据挖掘,通过抓取微博排行榜的文章,掌握舆情动向数据聚合,比如企查查,抓取企业官网的详细信息导购、价格比对,通过抓取购物网站的商品页面获取商品价格,为买家提供价格参考在面向计算机专业的人才招聘市场上,以爬虫为关键字搜索,可以获得大量的职位招聘:

1. 爬虫的定义

网络爬虫(又称为网页蜘蛛,网络机器人,在 FOAF 社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。—— 百度百科定义 详细定义参照慕课网注解: 爬虫其实是一种自动化信息采集程序或脚本,可以方便的帮助大家获得自己想要的特定信息。比如说,像百度,谷歌等搜索引擎,他们的背后重要的技术支撑就是爬虫。当我们使用搜索引擎搜索某一信息的时候,展现在我们眼前的搜索结果,就是爬虫程序事先从万维网里爬取下来的。我们之所以称之为爬虫,只不过是对自动获取万维网的动作的形象比喻而已。

3.为网页添加背景音乐

这里我们要给大家讲解一个好用的神奇的标签,就是 bgsound ,我们可以写一个这样的标签到网页的 body 标签里。 <bgsound src=""> 其中双引号中的部分,需要用你的本地音频文件目录位置进行替换。把这个标签粘贴到网页的 body 中,就可以为网页设置背景音乐了。由于是音频,所以老师就无法截图给大家说明了,大家只要按找老师说的方式去操作,就会很容易的给网页添加了背景音乐。

3.设置字段验证规则

字段的验证规则可以在 protected $rule 中设置如下规则: /** * 设置字段验证规则 * @var string[] */ protected $rule = [ 'name' => 'require|max:5', 'age' => 'number|between:1,120', 'id_number' => 'require|in:18', ];如下图所示:

动态规划算法实战

本小节会以 leetcode 上的 4 道编程题来进行动态规划算法的实战,以帮助大家更好的理解和掌握动态规划算法。

2. 后进先出

周末陪孩子玩新买的玩具枪,看到弹夹我乐了,这不就是一个栈容器吗!儿子问我什么是栈,我反问儿子,你装弹的顺序和子弹打出去的顺序有没有关联或规律呢?儿子想了一会说,最先装进去的子弹要等到最后才能被发射出去,而第一发子弹是最后一个装进去的!(图片来源于网络,版权归原作者所有)正像枪的弹夹一样,栈表示的是一个后进先出的对象,也叫堆栈。无需百度,直接打开 java.util.Stack 源码还能看到 Java 为此定义了一个专属单词 LIFO ,其实就是 last-in-first-out 的缩写。细心的小伙伴还会从源码中发现 Stack 其实是继承自 Vector ,上一节我们介绍了数组, Vector 就是可实现自动增长的对象数组,它支持线程的同步。所以我们可以发现,栈的本质也是数组。数据从栈顶压入,操作的时候先从栈顶取出。

3.10 控制规则

控制规则其实就是我们前面章节讲的 Sass 控制指令,它们包括 @if 、@each、@for 和 @while,它们的功能在前面的章节我们已经做了详细的讲解,此处我们回忆一下,它们一般用于判断和循环的逻辑,用来对你的逻辑代码进行流控制。

4.1 location 匹配规则

规则匹配=严格匹配。如果请求匹配这个 location,那么将停止搜索并立即处理此请求~区分大小写匹配(可用正则表达式)~*不区分大小写匹配(可用正则表达式)!~区分大小写不匹配!~*不区分大小写不匹配^~前缀匹配@“@” 定义一个命名的location,使用在内部定向时/通用匹配,任何请求都会匹配到

5. 信息综合搜索

信息的搜集往往不是单一的,是由类似上面列举的很多方式的组合。我们经常听到一个词 人肉搜索,大家都很惊讶网络神人技术太强,其实主要还是因为我们散布在网上的资料信息太多了。这些零碎的资料拼一拼还是能获得很全的信息的。搜索引擎随便输入你的名字,或者外加几个关键词可能查到你在哪所学校,参加了某某活动,获得了某某名次的奖励你在哪所公司,缴交的一些社保信息你在某个网站的评论根据你的昵称到 QQ 上面搜索,同一个昵称到处用概率还是很大的,如果有手机号那就更加准确了,紧接着可以根据你的 QQ 空间获取更多你私人的信息。(这以前是非常好查的,现在腾讯也一直在完善信息安全这块)也可能是到其他平台去搜索:微博,头条,人人网,58同城 等照片网上搜索相似百度搜索引擎就有根据图片搜索到功能到政府的一些网站,如 信用xx ,上面根据法人名字也能搜索不少有价值的东西。

3.2 序列化规则

使用 JSON.stringify 有些内置规则。如果对象中存在包装对象,则在转换过程中会变成原始值。var obj = { string: new String('A promise is a promise.'), number: new Number(996),};var result = JSON.stringify(obj);console.log(result); // 输出:"{"string":"A promise is a promise.","number":996}"如果转换的对象或者对象下的属性存在 toJSON 方法,那么这个方法的返回值会作为转换结果。var user = { nickname: 'joker', toJSON: function() { return 'hahahahahahaha'; },}var result = JSON.stringify(user);console.log(result); // 输出:"hahahahahahaha"可以看到结果为 toJSON 方法的返回值。除了数组以外的对象,转换结果顺序为随机。var obj = { b: 2, c: 3, a: 1,};如以上对象,转换的结果有可能是以下情况中的一种:"{"a":1,"b":2,"c":3}""{"a":1,"c":3,"b":2}""{"b":2,"a":1,"c":3}""{"b":2,"c":3,"a":1}""{"c":3,"b":2,"a":1}""{"c":3,"a":1,"b":2}"undefined、ES6 中的 symbol 值、函数在转换过程中都会被忽略,当然函数如果具有 toJSON 方法依然会优先选择 toJSON 方法的结果。var fn = function() {};fn.toJSON = function() {return '我是函数'};var result = JSON.stringify({ a: fn, b: Symbol(1), c: undefined, d: function() {},});console.log(result);存在循环引用,则会报错var obj1 = { prop1: 1,};var obj2 = { prop1: 1,};obj1.prop2 = obj2;obj2.prop2 = obj1;JSON.stringify(obj1); // TypeError: Converting circular structure to JSON两个对象相互引用之后,进行系列化就会抛出错误。在 ES6 中,symbol 可以作为对象的属性值,但在处理的时候都会被忽略。var symbol = Symbol();var obj = { prop1: 'value1', [symbol]: 'value2',};console.log(obj);var result = JSON.stringify(obj);console.log(result); // 输出:{"prop1":"value1"}null、正负 Infinity、NaN 在序列化时都会被当作 null 。var obj = { null: null, infinity1: +Infinity, infinity2: -Infinity, NaN: NaN,};var result = JSON.stringify(obj);console.log(result); // 输出:{"null":null,"infinity1":null,"infinity2":null,"NaN":null}

2.3 变量的命名规则

Python 的变量名称具有如下规则:2.3.1 变量名由字母、数字、下划线组成合法的变量名称如下:abcABCabc123abc_xyzabc__xyz,该命名包含了2根下划线__init__,该命名包含了2根下划线不合法的变量名称如下:a$bc,该命名包含了字符$ab/c,该命名包含了字符/2.3.2 数字不能作为变量名开头合法的变量名称如下:abc123不合法的变量名称如下:123abc2.3.4 不能以 Python 中的关键字命名在 Python 中,具有特殊功能的标识符称为关键字。关键字是 Python 语言自己已经使用的了,不允许开发者自己定义和关键字相同名字的变量。下图列出了 Python 中所有的关键字。Python 中的关键字在 Python 的交互模式中,输入’False = 123’,定义变量 False,初值为 123,输出结果如下:>>> False = 123 File "<stdin>", line 1SyntaxError: can't assign to keywordFalse 是 Python 的关键字,因此提示语法错误:“SyntaxError: can’t assign to keyword”。

3.4 平台标识

也就是%PLATFORM% 可取值如下:值平台APP-PLUS5+AppH5H5MP-WEIXIN微信小程序MP-ALIPAY支付宝小程序MP-BAIDU百度小程序MP-TOUTIAO头条小程序MP-QQQQ小程序MP微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序

百度

当我们点开百度的时候会发现它的图标也是雪碧图:它的图标是靠着雪碧图中不同的图标来切换颜色的。

3. 变量命名规则

为了更方便程序的阅读,以及让程序更加的规范,给变量命名的时候不可以随意命名,需要遵守变量的命名规则:变量名称可以是由字母,数字,下划线( _ )组成;字母可以是大写字母,也可以是小写字母;单个字母可以作为变量名,但是单个数字和下划线不可以单独作为变量名;当组成变量名的字符大于等于 2 个时,字母和下划线可以作为变量名第一个字符,但是数字不可以;理论上变量名的长度是没有限制的,但是有的编译器超过 31 个字符就会产生错误。不过超长的字符变量名也会给编写和阅读程序带来不便。Tips:请注意英文字母变量的大小写。在 Linux 以及 Unix 系统中,是严格区分大小写的。int A 和 int a ,会被认为是两个不同的变量。实例:int A, a, _A, c0, _ddf5, res_1;Tips:C 语言可以一行代码声明多个变量。上面举了几个符合规则的变量名的例子。但是合乎规则不等于是合格的变量名。具体的变量名最好与要存储的内容有一定关联,便于程序阅读。例如我的变量中要存储的是数学成绩分数,那么变量名可以叫做:int Math_scores;

4. 模板方法模式

模板方法模式是定义一个操作中的算法的骨架,从而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。通常对于一些重要的复杂方法和多个子类共有的方法且逻辑相同的情况下会使用模板方法模式。比如用户第三方用户认证的时候就比较适合使用模板方法。我们来看一个例子:假设我们现在需要用到微信、微博的第三方用户授权来获取用户的信息。//使用模板方法模式描述获取第三方用户信息的过程 public abstract class Authentication{ public void checkUserAuthentication(){ checkIdentity(); fetchInfo(); } ​ protected abstract void checkIdentity(); protected abstract void fetchInfo(); } ​ //微信用户 public class WechatAuthenication extends Authentication{ @Override protected void checkIdentity() { System.out.println("获得微信用户授权"); } ​ @Override protected void fetchInfo() { System.out.println("获取微信用信息"); } } ​ //微信用户 public class WeiboAuthenication extends Authentication{ @Override protected void checkIdentity() { System.out.println("获得微博用户授权"); } ​ @Override protected void fetchInfo() { System.out.println("获取微博用信息"); } } ​ //调用模板方法 public class Demo{ public static void main(String...s){ Authentication auth = new WechatAuthenication(); auth.checkUserAuthentication(); auth = new WeiboAuthenication(); auth.checkUserAuthentication(); } }输出结果:获得微信用户授权 获取微信用信信息 获得微博用户授权 获取微博用信信息现在我们使用 Lambda 表达式换个角度来思考模板方法模式。如果我们用函数式接口来组织模板方法中的调用过程,相比使用继承来构建要显得灵活的多。//定义一个处理接口,用来处理一项事务,如授权或者获取信息。 public interface Processer{ public void process(); } ​ //封装调用过程 public class Authentication{ private final Processer identity; private final Processer userinfo; public Authentication(Criteria identity,Criteria userinfo){ this.identity = identity; this.userinfo = userinfo; } ​ public void checkUserAuthentication(){ identity.process(); userinfo.process(); } } ​ //使用模板方法 public class Demo{ Authentication auth = new Authentication(()->System.out.println("获得微信用户授权"), ()->System.out.println("获取微信用户信息")); auth.checkUserAuthentication(); auth = new Authentication(()->System.out.println("获得微博用户授权"), ()->System.out.println("获取微博用户信息")); auth.checkUserAuthentication(); }输出结果:获得微信用户授权 获取微信用信信息 获得微博用户授权 获取微博用信信息此时,我们的模板方法得到了大幅的简化,同时通过函数接口让模板方法获得了极大的灵活性。

1. Shell 脚本的构成及规范

Shell 脚本有一些约定俗成的规范,大家都遵循这些规则,编写出来的脚本更能被大家接受,Shell 脚本其实不能称为一门编程语言,它更像是一个工具,用来杂糅不同的程序及命令供我们调用来完成自己的预期操作。

4. 各平台小程序组件存放目录

uni-app 还有一个非常牛的地方,就是支持在 App 和小程序中使用小程序自定义的组件,支持情况如下:平台支持情况小程序组件存放目录 H5 从 HBuilderX2.4.7 起,支持微信小程序组件 wxcomponentsApp(不含 nvue)支持微信小程序组件 wxcomponents 微信小程序支持微信小程序组件 wxcomponents 支付宝小程序支持支付宝小程序组件 mycomponents 百度小程序支持百度小程序组件 swancomponents 字节跳动小程序支持字节跳动小程序组件 ttcomponentsQQ 小程序支持 QQ 小程序组件 wxcomponents

首页上一页1234567下一页尾页
直播
查看课程详情
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号