前言
最近不是很忙,Flutter和RN都有点整不动了,(此时流下了老奶奶基础太差,脑子又笨,咸咸的泪水),想着补补基础,于是就有了以下的笔记
笔记
小程序中的view类似于html中的div,那是块状结构(此处完全不懂块是啥玩意儿,默默的去查了一下,css中块级元素和行级元素的区别,以及微信小程序中的行级和块级元素),默认会占一行,多个view的话,可能会纵向排列,如果不想每个占一行的话,可以设置为行内元素,display:inline,但inline内是不能设置高和宽的,所以可以设置为display:inline-block,然后再设置高和宽
多个样式可以连续设置
<view class='chunk color1'/>
- 一般情况而言,对于view控件来说,高度会自适应,会根据里面填充的元素,动态的决定它的高度,宽度会是100%
就是比如row,row-reverse,column,column-reverse效果会不一样
reverse后,排列方向也会发生变化,比如row是左对齐,reverse后,会变成又对齐
- 当子控件没有设置高度的时候,父控件设置了align-items中的stretch后,会有个拉伸的效果,如果子控件明确设置了高度,则strecth会没有效果
- align-items中的baseline会保证每个子元素中的文字是对齐的,baseline会参考第一个子元素中的文字的底线作为基准,其他的子元素会根据这个基线,自动调整自己的位置
- 如果没有设置换行的话,每个元素加起来的宽度如果超过了屏幕的宽度,则会自动压缩每个控件,平均每个都会缩小一点,如果想换行的话,可以使用flex-wrap:wrap,如果想要消除换行后的间距(默认会在换行后,剩余的空间中,将换行过去的内容居中排列),则需要算高度,给个固定的高度
- 相对路径和绝对路径,如果在最前面加上一个/,表示绝对路径,从项目的最根目录开始算起,如果么有/的话,则是从当前文件的位置开始算起
/* 这里使用了子元素选择器的写法,但这种写法有个缺陷,就是不能复用,如果想把一个样式用在多个组件上的时候,可以给每个样式起个名字,小程序目前还支持子弹选择器等多种选择器,并不局限于文档中的几个 */
.container image{
width: 32rpx;
height: 28rpx;
}
- 字体
.container text{
/* 苹方细体,只在ios系统中有效,在android中无效,如果电脑是苹果电脑的话,如果是用的安卓模拟器,则也是有效果的,主要是因为苹果电脑默认字体就是苹方 ,而在安卓中的默认字体是思源*/
font-family: "PingFangSC-Thin";
font-size: 48rpx;
color: #bbbbbb;
}
每个页面,小程序默认会在最外层添加一个page标签(可以在调试器中的
Wxml
面板中查看到),所以当在全局app.wxss中设置page的样式后,会默认应用到每个页面去,这个就叫样式的继承,如果想修改的话,可以单独在自己的页面,做修改,这样会覆盖掉全局的样式关于样式的继承:
- 不是所有的全局样式都能够被组件继承,只有很少的部分能够被继承,在自定义组件中,只有font,color会从组建外继承到组件内
- 但是几乎所有的样式都能够被page页面继承
- text中文字的四周默认都会有一个间距,消除间距的方法是:如果设置字体大小为24rpx,那么可以将行高line-height也设置为24rpx,这样就可以消除行高了
- 对于位置的偏移,在css中常用position来设置,比如position:relative
.container text{
font-size: 24rpx;
/* 将行高和字体设置得一样大,可以消除文字的间距 */
line-height: 24rpx;
color: #bbbbbb;
position: relative;
bottom: 10rpx;
left: 5rpx;
}
- 将组件设置为flex后,可以消除子组件的块状属性,但并不能消除组件自己本身的块状属性
.container{
/* 将display设置为inline-flex后,可以消除自己和子元素的块状属性,相当于将宽度设置为自适应 */
display: inline-flex;
flex-direction: row;
padding: 10rpx;
}
- 关于事件绑定和冒泡:bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡
- 组件:
一般对于组件内部的数据,都定义在data中 - 在小程序中,对于通过判断在wxml中显示不同的值的情况下,可以使用三元表达式,如果是在image内部的话,image的src路径如果在{}内部,则可以将路径用单引号括起来,比如:
<image src="{{like?'images/like.png':'images/unlike.png'}}"
- 对于组件的属性:
/**
* 组件的属性列表,即会开放出去的属性
*/
properties: {
//如果这里属性比较多的话,可以将其包裹成一个对象
like: {
// 目前小程序只可以设置以下三个值,其中type为必填,value和observer为选填
type: Boolean,
// // 初始值,如果初始值为false的话,没有必要写,因为boolean的默认值本来就是false,所以当初始值要为true时,才有必要写
// value: false,
// // 监听方法,当我们改变了index的值的时候,微信小程序会主动地来调用该方法,newVal代表改变之前的数值,oldVal代表改变之后的数值
//但是千万不要在observer中尝试修改index本身的值,否则可能会造成无限递归的情况
// observer(newVal,oldVal,changedPath){
// }
},
count: {
type: Number,
}
},
/**
* 组件内部的数据定义在此,即内部的私有属性
*/
data: {
likeSrc: "images/like.png",
unLikeSrc: 'images/like@dis.png'
},
在properties中定义的属性,主要是用于外部传入数据,比如:
<z-like like="{{classicData.like_status}}" count="{{classicData.fav_nums}}" />
其中properties是要暴露出去的属性,外部可以访问的属性,而data内部的属性则是组件内部使用的私有属性,不对外开放
- 如果要取properties或者data中的数据,使用this关键字
- let和var的区别:
let允许你生命一个作用域被限制在块级中的变量、语句或者表达式。与var关键字不同的是,它生命的变量只能是全局或者整个函数块的。var的作用域要更大一点,以前写过java的可能会更习惯于用let一点,python的可能更习惯于var一点 - 网络请求有三种形式:GET(获取数据),POST(提交参数),PUT(修改数据)
- 网络请求一般放在小程序生命周期中的onLoad中
- 一般情况下,只要服务器返回了结果,不管是2、3、4、5开头的,都会走success方法,如果网络出了问题,则会走fail方法
- 小程序一般不允许随意访问一个url,如果要访问的话,必须在小程序的后台账号中,
将该域名添加到合法域名列表中
才可以访问,这是一个方法,另外还有一个方法(只适用于开发阶段,如果最后你的小程序要上线发布的话,还是需要按照第一种方法来设置噢)就是:
-
当我们遇到一个网络请求出现错误的时候,最好的办法就是打开调试器中的Network面板,点击这个错误,查看具体的错误信息,才能知道错在哪(如果错误为500,那么肯定是服务器错误,其他的就需要你自己多多查看自己代码哪里有问题了)
如果是返回正常的数据,那结果也可以点开Name来查看
- 关于this的指代问题:在回调函数中,使用this.data.****,某个属性,this是不明确的,会为null,在es6之前,传统的做法为:在回调函数之外,使用
let that=this
,先将this,赋值给一个变量,在回调函数中使用that这个变量。而在es6中,有个更好的解决办法:使用箭头函数
data: {
test:1
},
onLoad: function (options) {
console.log(this.data.test)
wx.request({
url: 'http://bl.7yue.pro/v1/classic/latest',
header:{
appkey:"K5H3SiFRY9qLzs0n"
},
success:function(res){
//这里会报错
console.log(this.data.test)
}
})
},
解决方法一:
onLoad: function (options) {
console.log(this.data.test)
let that=this
wx.request({
url: 'http://bl.7yue.pro/v1/classic/latest',
header:{
appkey:"K5H3SiFRY9qLzs0n"
},
success:function(res){
//使用that替代
console.log(that.data.test)
}
})
},
解决方法二:
onLoad: function (options) {
console.log(this.data.test)
wx.request({
url: 'http://bl.7yue.pro/v1/classic/latest',
header:{
appkey:"K5H3SiFRY9qLzs0n"
},
//使用箭头函数
success:(res)=>{
console.log(this.data.test)
}
})
},
- 使用Promise的场景:异步嵌套,也就是
回调地狱
如果你的异步操作没有回调的嵌套,只有一次操作,那就完全不需要使用Promise,滥用Promise反而会增加代码的复杂度
Promise的简单用法(解决回调地狱问题)
apiOne()
.then(res=>
return apiTwo(res)
)
.then(res=>
return apiThee(res)
)
.then(res=>
//……
)
每次的异步调用之间是平级的关系,不像以前那样,在回调中调用,在回调的回调中调用
-
关于const常量:不能修改该常量的内存地址,否则会报错
- ES6中的导入与导出:
es5中如果要导入一个类或者其他的,需要使用到require,而在es6中的话,导出只需加上export,导入的地方使用import即可
导出的地方
export const config={
api_base_url='http://bl.7yue.pro/v1/',
appkey: "K5H3SiFRY9qLzs0n"
}
// 也可以写成以下的方式:
// export {
// config
// }
// 或者
// export {
// //这里起了别名的话,在导入的地方要直接使用别名哦,而不能使用config了哦
// config as 别名
// }
导入的地方
// 这里的config必须和导出地方的源常量名一致,如果不想用原来的名字,则可以使用import{config as 别名} from '/config.js'
import {
config
} from '/config.js'
class HTTP {
request(params) {
wx.request({
url: params.url,
header: params.header,
method: params.method
})
}
}
- 在import的时候尽量使用相对路径,不要使用绝对路径
- 在小程序中,setData中的所有数据都可以在调试器下面的AppData面板中看到
- 凡是要被wxml使用的变量,最好都在data中定义一下,给个初始值也好,比如:
data: {
classicData:null
},
onLoad: function (options) {
classic.getLastest((res)=>{
console.log(res)
this.setData({
// classicData是要传递到wxml中去,被wxml使用的变量,最好在data中初始化一下
classicData:res
})
})
},
- 关于自定义组件中的自定义事件
如果想与外部调用的组件通信,想把一些数据传递出去,则可以使用自定义事件triggerEvent来完成,
this.triggerEvent("自定义事件名称",{自定义事件参数},{其他设置})
33.如果想对data下面的值做初始化的话,不能给用Number或者String等,因为默认的Number和String是一个函数,而在properties中只是做了特殊处理才没有报错,如果想对data下的值做初始化,可以直接给值
34.不管是properties还是data,它们都指向同一个js对象,可以理解为它们两个最后会合并成一个js对象,所以就算它们两个表面上内部的属性不一样,但打印出来会是一模一样的,最后会指向它们两个的一个合集,但两者内部最好不要有同名的属性,不然合并后会data中的会覆盖properties中的同名属性的值,而区别就是properties中的值会取给定的默认值,而data中的会是js中内置的函数,要设定初始值的话,可以类似以下这种设置方法
- display:inline-flex???
- 如果多个组件有同样的属性和行为,那么可以定义一个behavior(类似component,有properties,data,以及methods),而一个组件可以继承多个behavior,所以在component中的behaviors是个数组。而component和behavior如果有同样的属性或者方法的时候,就需要一个规则来决定最后用哪个:
- 一般私有函数是放在类中的最下面的
- 模板字符串:将单引号改为反引号,并在变量前面加上$以及{},比如
url: 'classic/' + category + '/' + artID + '/favor'
,改为模板字符串后:
url: `classic/${category}/${artID}/favor`
- 扩展运算符:"..."使用三个点,可以将一个对象进行展开,这个在绑定wxml的时候比较有用,比如传入一个对象item,在wxml中需要item.title,item.img一个一个的传的话,略微不简洁,则可以在传入的时候就直接使用
...item
,将对象item展开后传入,然后在wxml中就不用写前面的item了
比如使用扩展运算符之前
js中
onLoad(options) {
classicModel.getLastest((res) => {
console.log(res)
this.setData({
// classicData是要传递到wxml中去,被wxml使用的变量,最好在data中初始化一下
classicData: res
})
})
},
wxml中
<view class ="container">
<view class='header'>
<z-epsoide class="epsoide" index="{{classicData.index}}" />
<z-like class="like" bind:like="onLike" like="{{classicData.like_status}}" count="{{classicData.fav_nums}}" />
</view>
<z-movie img="{{classicData.image}}" content="{{classicData.content}}" />
<z-navi bind:left="onNext" bind:right="onPrevious" title="{{classicData.title}}" first="{{first}}" latest="{{latest}}" class="navi" />
</view>
而使用扩展运算符之后
js中
onLoad(options) {
classicModel.getLastest((res) => {
console.log(res)
this.setData({
...res
})
})
},
wxml中
<view class ="container">
<view class='header'>
<z-epsoide class="epsoide" index="{{index}}" />
<z-like class="like" bind:like="onLike" like="{{like_status}}" count="{{fav_nums}}" />
</view>
<z-movie img="{{image}}" content="{{content}}" />
<z-navi bind:left="onNext" bind:right="onPrevious" title="{{title}}" first="{{first}}" latest="{{latest}}" class="navi" />
</view>
而有时候,如果你确定只有一个参数的时候,参数外面不需要小括号,箭头函数后面的部分如果只有一行的话也不需要花括号
比如:
const promise = new Promise((resolve, reject) => {
wx.getSystemInfo({
success:(res)=> {
//信息获取成功后,通过resolve将状态修改为resolve
resolve(res)
},
fail:(error)=> {
//信息获取失败后,通过resolve将状态修改为reject
reject(res)
}
})
})
可以修改为:
const promise = new Promise((resolve, reject) => {
wx.getSystemInfo({
success:res =>resolve(res),
fail:error=>reject(res)
})
})
- 在wxml中控制控件的显示与隐藏:可以使用小程序中提供的
条件渲染
语句:wx:if="{{***}}"
,如果括号内的内容为真,那么该控件就显示,否则就隐藏:
而另外一种控制显隐的方法是使用hidden
,在普通的控件中是有效的,但hidden对于自定义组件会失效,可能是因为自定义组件会将hidden当成一个普通的属性,解决办法就是在自定义组件的properties内部,自己新建一个hidden属性来达到目的。而hidden和wx:if也是有区别的:
如果切换得比较频繁的话,就用hidden吧。但是在组件中,有hidden的话,是不会出发detached方法,但wx:if就可以,因为使用wx:if的话,每次切换都会执行一次完整的生命周期,所以文档中有句话说的是一般来说,wx:if有更高的切换消耗而hidden有更高的初始渲染消耗,因此,如果需要频繁切换的场景下,用hidden更好,如果在运行时条件不大可能改变则用wx:if更好
,hidden在被初始化之后,就不会再去多次执行生命周期函数,只会做单纯的显示与隐藏 - 对于音乐播放的控制,以前的话是使用老板api,这个使用是调用一个一个的方法:
现在推荐使用新版api,这个对象会有一些非常有用的属性和方法,相对要方便点:
wx.getBackgroundAudioManager()将会返回一个backgroundAudioManager
对象,由这个对象来进行音乐的播放控制
- 对于在小程序中实现动画有几种方法:直接使用动画API,另外一种方法就是使用CSS3自己去编写,还有一个就是canvas
- airbnb的js规范中都给出了每一个规范的eslint(代码规范和错误检查工具,可以用来约束整个团队的代码风格)??
let date=new Date()
let year =date.getFullYear()
this.setData({
year:year,
})
用eslint属性值简写优化后:
let date=new Date()
let year =date.getFullYear()
this.setData({
year,
})
- 处理异步的几个方案:
- 纯粹的callback
- promise
- async await ES2017 小程序目前不支持
- Promise有三种状态
- pending 进行中
- fulfilled 成功
- rejected 失败
promise的基本用法:
//promise使用对象的方式,保存了异步调用的结果
const promise = new Promise((resolve, reject) => {
wx.getSystemInfo({
success:(res)=>{
//信息获取成功后,通过resolve将状态修改为resolve
resolve(res)
},
fail:(error)=> {
//信息获取失败后,通过resolve将状态修改为reject
reject(res)
}
})
})
//then有两个参数,一个是成功,一个是失败,分别对应上面的resolve和reject
promise.then((res) => {
console.log(res)
}, (error) => {
console.log(error)
})
- es6中的解构???,下面是
对象的解构
,其他的还有数组的解构
在传参中,将所有参数用大括号括起来,则可以直接传一个对象进去,并每个参数需要写上参数名,比如:
request(url,data={},method='GET')
传参的时候
this.request({
url,{
name:'zoe',
age:18
},'POST'
})
修改后:
request({url,data={},method='GET'})
传参:
this.request({
url:url,
data:{
name:'zoey',
age:18
},
method:'POST'
})
传参的时候就会显得比较清晰和明确
- 对于absolute,在css文档中,position总共有四个值,分别为
absolute
fixed
relative
static
,如果不给值得话,默认会是static。而absolute都会有个参照元素(一般都是其父元素),这个参照元素的父元素不能是static的。如果子元素为absolute,那么子元素如果想要参考父元素来定位的话,父元素就需要是非static的
- 对于position中的fixed属性:
.header{
/* fixed会让header始终保持在一个固定的位置,如果想在最上层的话还需要设置一个z-index */
position: fixed;
background-color: white;
height: 100rpx;
width: 100%;
border-top: 1px solid #f5f5f5;
border-bottom: 1px solid #f5f5f5;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
box-shadow: 0 0 3px 0 #e3e3e3;
z-index:99
}
就是下图中“搜索书籍”一栏能够固定在顶部的效果
- 关于wx:for的key:
<view class='books-container'>
<!-- 如果列表本身就是数字或者字符串,那么key可以直接写成wx:key="*this" -->
<block wx:for="{{books}}" wx:key="index">
<z-book book="{{item}}"/>
</block>
</view>
- 组件接收参数是通过properties接收的,而页面接收的参数,全部在页面的
onLoad
方法中的options
参数中,比如:
外部给当前页面传一个id,则在该页面,获取id的写法如下:
onLoad(options){
const id=options.id
}
- 微信小程序有三种编译模式:
- 普通编译模式 每次重新编译,都会从app.json中排在第一个页面的位置重新启动
- 添加编译模式 可以自己定义编译模式,也就是指定一个启动页面,不用每次都回到首页
- 通过二维码编译
下面介绍以下第二种编译模式:
点击顶部“普通编译”框,选择下拉列表中的“添加编译模式”
取一个模式名称,然后在“启动页面”处下拉选择你要首先展示的页面
然后给定一个该页面需要传入的参数,就可以了
然后看编译模式那里,就能看到刚刚自定义的模式了。选择该模式,每次编译后,首先就进入你希望的页面了。方便调试
- 在flex模式下,margin-bottom才会生效 ?
- 在自定义组件内部还有个高级的东西:slot(插槽),一个slot相当于一个占位符,如果外部传入标签,那么就会将插槽替换成传入的标签,如果不传,那么就会是一个空的插槽,空的插槽是不会被渲染和显示的
一个组件内部可以有多个插槽,他们之间是用name
进行区分
tag.wxml
<view class='container'>
<slot name="before" />
<text>{{text}}</text>
<slot name="after" />
</view>
要在组件内部加上插槽,需要将使用组件的wxml中的组件写成双标签样式,并在标签内部,加入要添加的部分,并声明要对应的插到哪个槽上(slot="插槽名")
book-detail.wxml
<z-tag text="{{item.content}}">
<text slot="before">^_^</text>
<text slot="after">{{' +'+item.nums}}</text>
</z-tag>
启用插槽:在组件内部,写上
tag.js
options: {
//启用插槽
multipleSlots: true
},
options:{
multipleSlots:true
}
- 不能直接对自定义组件书写css样式,可以通过:
-
子元素选择器或者后代选择
强行给自定义组件的内部组件设置样式(这种方式违反了组件封装原则) -
组件的属性和slot
给自定义组件传入你想要的样式 外部样式(externalClass)
全局样式(globalClass)
- 子元素选择器与后代选择器:
/* 后代选择器
.comment-container z-tag:nth-child(1) view{
background-color: #fffbdd;
} */
/* 子元素选择器
.comment-container > z-tag:nth-child(1) > view{
background-color: #fffbdd;
} */
/* 子元素选择器
.comment-container > z-tag:nth-child(2) > view{
background-color: #eefbff;
} */
/* 子元素选择器 选择奇数*/
.comment-container > z-tag:nth-child(odd) > view{
background-color: #eefbff;
}
/* 子元素选择器 选择偶数*/
.comment-container > z-tag:nth-child(even) > view{
background-color: #fffbdd;
}
-
外部样式
的使用:
如果想要实现同上面子元素选择器同样的效果:
使用外部样式的方式,需要按照以下步骤来:
在组件内部js中定义externalClasses属性
//外部样式,接收组件外部传入进来的样式,可以有多个
externalClasses: [
'tag-class',
],
在组件内部的wxml中使用定义的externalClasses:
<!-- 这里container代表的叫普通样式,而tag-class代表的为外部样式,外部样式要放在普通样式之后,这样可以在外部对原有的样式做一定的覆盖(会覆盖这个真的是一厢情愿,小程序好像并没有做这样的处理,尴尬,所以括号外的上一句话请忽略,小程序实际的做法是,如果你要传入外部样式,那你原来的样式就不要要了,只能选择一个),补充 -->
<view class='container tag-class'>
<slot name="before" />
<text>{{text}}</text>
<slot name="after" />
</view>
在外部定义即将要传入的样式
book-detail.wxss
.ex-tag1 {
background-color: #fffbdd;
}
.ex-tag2 {
background-color: #eefbff;
}
在外部使用,传入我们自定义的样式:
book-detail.wxml
<z-tag tag-class="{{index==0?'ex-tag1':''||index==1?'ex-tag2':''}}" text="{{item.content}}">
<text class='num' slot="after">{{' +'+item.nums}}</text>
</z-tag>
但是小程序目前不能实现外部样式覆盖内部样式,也就是普通样式和外部样式同时只能有一个,但可以有一个强行实现的办法:在外部定义即将传入的样式的时候,在样式末尾加上!important
,提升样式的优先级,强行实现(可能还有其他办法,欢迎告诉我):
book-detail.wxss
.ex-tag1 {
background-color: #fffbdd !important;
}
.ex-tag2 {
background-color: #eefbff !important;
}
- 全局样式类的使用:
// comp-a.js
Component({
options: {
addGlobalClass: true,
}
})
<!-- comp-a.wxml -->
<text class="text red-text">THIS IS A</text>
/* comp-a.wxss */
.text{
color: blue;
font-size: 80rpx;
font-weight: 400;
}
//comp-b.js
Component({
options: {
addGlobalClass: true,
}
})
<!-- comp-b.wxml -->
<text class="text">THIS IS B</text>
/* comp-b.wxss */
.text{
color: orange;
font-size: 40rpx;
font-weight: 400;
}
{
"usingComponents": {
"comp-a": "/components/comp-a/comp-a",
"comp-b": "/components/comp-b/comp-b"
}
}
<!-- index.wxml -->
<view class='container'>
<comp-a/>
<comp-b/>
</view>
/* index.wxss */
.container{
display: flex;
flex-direction: column
}
.red-text {
font-size: 20rpx;
color: red !important;
}
总的来说可以达到外部样式类的效果,而且还比外部样式类的方式简单一点
- wxs:让wxml具备写js或者调用js的能力,主要作用可以用来编写小程序的过滤器,比如:
需求:将text中的\\n替换为\n
定义一个filter.wxs
// 将\\n替换成\n
var format = function(text) {
if (!text) {
return
}
var reg = getRegExp('\\\\n', 'g')
// & nbsp;表示空格
return text.replace(reg, '\n ')
}
module.exports = {
format: format
}
在使用的地方,比如book-detail.wxml中
<wxs src="../../util/filter.wxs" module='filter' />
……
<text class='content' decode='{{true}}'>{{filter.format(book.summary)}}</text>
……
也可以直接在wxml中定义
<wxs module="filter">
var limit = function(array, length) {
return array.slice(0, length)
}
var format = function(text){
if(!text){
return
}
var reg = getRegExp('\\\\n','g')
var text = text.replace(reg,'\n ')
return text
}
module.exports = {
limit: limit,
format:format
}
</wxs>
- 设置段落开头的距离:
text-indent
(规定文本块中首行文本的缩进,允许使用负值。如果使用负值,那么首行会被缩进到左边) - padding的描述的顺序(margin同理哈)
- white-space,它经常和overflow和text-overflow一起使用,比如:
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden
表示多余的不换行,多余的隐藏并显示省略号,参考
- 在wxml中写动画,比如:
.rotation{
/* linear匀速播放,infinite无限播放 */
animation: rotation 12s linear infinite;
}
@keyframes rotation{
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
- Promise.all(),可以组合多个promise,使用方法:
const promise4 = Promise.all([promise1,promise2,promise3]),它内部是一个数组,可以有多个promise,然后它会返回一个新的promise
只有当内部所有的promise都返回结果后,才会出发新的promise的then回调方法,比如可以用在一个页面有多个网络请求,但如果要加上Loading的话,需要加在所有页面完成之后,可以使用promise.all
onLoad: function(options) {
wx.showLoading({
title: '加载中...',
})
const bid = options.bid
const detail = bookModel.getDetail(bid)
const comments = bookModel.getComments(bid)
const likeStatus = bookModel.getLikeStatus(bid)
//使用Promise.all取代下面三个单独的promise
Promise.all([detail,comments,likeStatus])
.then(res=>{
//这里res返回的是一个数组,一一对应的是传进去的参数的结果
//这里所有结果都返回后,才会执行该回调
this.setData({
book: res[0],
comments: res[1].comments,
listStatus: res[2].like_status,
likeCount: res[2].fav_nums
})
wx.hideLoading()
})
// detail.then(res => {
// this.setData({
// book: res
// })
// })
// comments.then(res => {
// this.setData({
// comments: res.comments
// })
// })
// likeStatus.then(res => {
// this.setData({
// listStatus: res.like_status,
// likeCount: res.fav_nums
// })
// })
},
- Promise.race([promise1,promise2,promise3]),返回的将是promise1,promise2,promise3三个promise中,竞争成功的那个promise,也就是返回速度最快的那个
//先判断历史记录中是否有该关键词
const has = words.includes(keyword)
//将keyword放到words数组中的第一位
words.unshift(keyword)
words.pop() //删除末尾的元素
- 做上拉加载更多可以使用Page页面中的
onReachBottom
方法,也可以使用scroll-view
组件 - 如果wxml中,绑定的有data中的变量的话,改变这个值必须要使用setData来进行,如果没有绑定的话,则可以直接使用=来赋值,比如:
this.data.loading=false - 一个会被多个地方使用到的功能,可以提取成一个behavior,比如上拉加载更多
- 不需要用户授权,就能获取到用户头像和昵称的方法(有缺陷):open-data
<open-data type="userAvatarUrl">
,这个只是微信用来显示相关信息的,并不会获取到相关信息。而如果想在js中拿到用户的相关信息,则需要授权,在老版本中,可以使用wx.getUserInfo
接口,然后界面会出现一个弹窗,询问用户是否愿意授权小程序来获取自己的信息。而新版本中,不能这样使用了,现在需要是用组件的方式而不是API的方法来弹窗了。这样是否弹窗的主动权掌握在用户自己手里,而不会一进某个页面就弹窗。wx.getUserInfo能获取到用户信息的前提是:已经获得授权。比如:
<button open-type="getUserInfo" bind:getuserinfo="onGetUserInfo">
用户授权后,将不再弹出授权框 - wx.getSetting,知道用户是否授权过,返回的值中authSetting如果有值,则为已授权,如果为空,则没授权
- 如果想从一个小程序跳转到另外一个小程序,那么这两个小程序,必须都要关注了同一个公众号
- 小程序跳转,还有个内置的组件叫navigator,如果要跳转到另外一个小程序,则需要知道另外一个小程序的app-id,比如:
<navigator class="nav" target="miniProgram" app-id="******" open-type="navigate">
<image class="vendor" src="/images/my/vendor.png"></image>
</navigator>