微信小程序相关知识点和云音乐项目制作遇到的问题及解决
小程序项目想下载项目的可以下载看看~
下载地址
- github地址: https://github.com/superBiuBiuMan/Wechat_NetEase_CloudMusic
- gitee地址: https://gitee.com/superBiuBiu/Wechat_NetEase_CloudMusic
弹性盒布局和移动端适配的一些知识
- 具体看下面这两篇博客,这里就不再继续说了
- 盒子模型及块元素水平垂直定位和绝对元素的定位布局和弹性盒
- 移动端前端的适配和rem,vm其他的一些的复习
微信小程序的适配方案
- 小程序适配单位:
rpx
- 小程序规定任何屏幕小的宽度为
750rpx
- 所以小程序会根据屏幕的宽度不同自动计算rpx值的大小
- 在
iPhone6
情况下(其实也就是DPR为2的情况下)1px
=2rpx
- 举个例子,比如设计师在iPhone6尺寸(375*667)下设计UI图,那么有一张图片的大小为
100px * 50px
,那么在微信小程序当中对应的rpx是多少呢? 相当于计算下方关系,当然,不需要我们自己去计算,微信小程序会自动转换 - 计算得结果等于200,所以是
200rpx
什么是响应式和自适应
- 一句话:响应式对不同页面做出代码变更,自适应不做代码变更
响应式
像素达到临界点就使用另外一套样式,通过媒体查询的方式,也就是据屏幕的大小自动的调整页面的展现方式
响应式的概念应该是覆盖了自适应,但是包括的东西更多了
自适应
- 百分比布局,宽度使用百分比,文字使用em,rem等
- 自适应是为了解决如何才能在不同大小的设备上呈现相同的网页
小程序配置
全局配置
- @官网全局配置API地址
- 小程序根目录下的
app.json
文件用来对微信小程序进行全局配置。文件内容为一个 JSON 对象,有以下属性: - 比如说配置页面底部的导航
- 比如说配置页面路由项目
- 比如说小程序标题名
页面配置
- @官网页面配置API
app.json
当中的部分配置项和对单个页面的配置项(二者通用)- 在全局配置当中需要有
window
字段,而单个页面的配置项.json文件当中是不需要添加window
字段的
全局配置(app.json
),需要添加window
字段
为某一个页面配置(比如说video页面video.json
),就不需要添加window
字段了
sitemap
- @官网sitemapAPI地址
- 用于被微信搜索爬取页面
小程序框架接口
App.js
App.js
只有一个,所以执行App({...})
在里面,而在每一个页面执行的是Page({...})
函数可以配置一些生命周期,并且可以用来全局数据
globalData
App.js当中内容代码如下
1 | App({ |
- 如果需要获取App.js所生成的实例化对象,其他js文件需要调用
getApp()
函数,经常用来读取设置的全局数据
1 | // other.js |
xxx.js(不同页面不同的xxx.js)
每一个页面js当中执行的是
Page({...})
函数,App.js
只有一个,执行App({...})
在里面不管有多少页码,每一个页面的
xxx.js
基本内容差不多都是这样子
1 | // pages/test/test.js |
WXML语法
- @官方API
- 和vue不同的是,vue一般对于变量是要在属性前添加
v-bind
或者简写为:
的,微信小程序则需要通过{{ js代码 }}
来操作变量
数据绑定
使用数据的一方
1 | <!--wxml--> |
- 提供数据的一方
1
2
3
4
5
6// page.js
Page({
data: {
message: 'Hello MINA!'
}
})
列表渲染
微信小程序如果需要操作的话,也需要绑定
key
值- 绑定key的时候,不需要书写
{{ }}
符号,直接传入key值,比如循环的每一项为item,里面有一个字段为id,那么传入wx:key
的时候只需要wx:key="id"
,而不是wx:key="{{id}}"
- 绑定key的时候,不需要书写
wx:for
语句有别与vue,在vue当中需要手动指明循环的变量,而微信小程序如果在不指定的情况下,循环项目自动命名为item
,当前循环的索引自动命名为index
,也可以使用如下代码去重命名,不过,一般都是二三层循环的时候才去,一般都是默认情况1
2
3使用 wx:for-item 可以指定数组当前元素的变量名,
使用 wx:for-index 可以指定数组当前下标的变量名:
1 | <!--wxml--> |
1 | // page.js |
条件渲染
在框架中,使用
wx:if=""
来判断是否需要渲染该代码块:
1 | <view wx:if="{{length > 5}}"> 1 </view> |
block wx:if
- 可以用于包括要判断的元素,并且不做渲染,这样子就不用在外面套一层
view
再去判断是否渲染了 <block/>
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
WXS文件
- @官方API - wxs
- 这里就不说啦,看这位博主写的就可以~
- @博客地址
事件系统/事件
- @官方API-介绍
- @官方API - 事件分类
- 在学事件之前,我们先回顾理解下标准事件流和非标准事件流
- 除上官网公布的事件之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(详见各个组件)
标准事件流
- 捕获: 从最外层祖先开始捕获
- 执行: 从最内层开始执行事件(执行相同的事件)
- 冒泡:从最内层开始执行,从内向外执行的过程交冒泡
非标准事件流
- IE浏览器专属
- 特点:没有捕获阶段
事件格式及示例
bind
+ 事件名 (不会阻止事件冒泡)catch
+ 事件名 (会阻止事件冒泡)- 常见的事件
tap
,就相当于PC端的click
示例
- 当用户点击该组件的时候会在该页面对应的 Page 中找到相应的事件处理函数。
1 | <!-- |
- 在相应的 Page 定义中写上相应的事件处理函数,参数是event。
1 | Page({ |
打印输出event
1 | { |
数据绑定
- 小程序没有自带的双向绑定,但是可以通过this.setData来实现修改数据后视图也变化
- this.data.key = value修改data当中的数据,注意和vue进行区分**,vue为什么不用加一层data,那是因为vue做了数据劫持**
- 这样子是不会引起视图的改变的! 小程序没有自带的双向绑定
- 如果想要触发视图中数据的更新,那么就需要借助
setData
这个方法用了,setData
的机制去把视图层和逻辑层做一个“中转站”两边连接起来。 注意这里的回调函数必须要用箭头函数,否者this指向不正确
如图
小程序获取,查询,元素/组件的信息
其功能类似于 DOM 的
getBoundingClientRect
获取元素节点信息语法格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16NodesRef.boundingClientRect(function callback)
//返回对象的信息均为px格式
function callback
回调函数,在执行 SelectorQuery.exec 方法后,节点信息会在 callback 中返回。
返回对象
属性 类型 说明
id string 节点的 ID
dataset Object 节点的 dataset
left number 节点的左边界坐标
right number 节点的右边界坐标
top number 节点的上边界坐标
bottom number 节点的下边界坐标
width number 节点的宽度(包括padding,包括border)
height number 节点的高度(包括padding,包括border)wx.createSelectorQuery()
- 返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用
this.createSelectorQuery()
来代替。
- 返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用
获取元素节点信息和查询节点案例
wxml
1 | <!--pages/boundingClientRect/boundingClientRect.wxml--> |
wxss
1 | /* pages/boundingClientRect/boundingClientRect.wxss */ |
js
1 | onLoad(options) { |
输出结果
1 | bottom: 166, |
vue和小程序都是单向数据流
什么是单向数据流
- 在父传子的前提下,父组件的数据发生会通知子组件自动更新
- 子组件内部,不能直接修改父组件传递过来的props => props是只读的
vue
单向数据流
但是实现了双向数据绑定 v-model 和 input事件结合使用
修改状态数据
- this.key = value
同步修改 model数据结构 和 视图同时修改
小程序
- 单向数据流
- 同步修改 model数据结构 和 视图 同时修改,通过
this.setData
App.json当中配置路由,路由跳转及需要注意的点
- @官方API-pages
- @官方API-路由跳转
- 微信小程序的路由和vue路由不同,小程序的默认路由会自动设置,即为配置项目
pages
数组的第一个
注意点
- App.json当中的配置项
pages
在配置路由页面的时候不可以再加上/
错误示范如下
1 | // 不要在前面添加 / |
正确示范如下
1 | { |
- 在路由跳转的时候,必须要加上
/
才可以正确跳转
1 | //关闭当前页面,跳转路由 |
- 不同的路由跳转会有所区别,有的是不允许跳转到 tabbar 页面 的
小程序使用分包
特点
- 加载小程序的时候先加载主播,当需要访问分包的页面时候才加载分包内容
- 分包的页面可以访问主包的文件,数据,图片等资源
- 目前小程序分包大小有以下限制:
- 整个小程序所有分包大小不超过
20M
- 单个分包/主包大小不能超过
2M
- 整个小程序所有分包大小不超过
主包
- 主包通常放置启动页(tabBar)页面
分包
- 除了主包,其他就都是分包了
常规分包和独立分包
常规分包
- 开发者通过在
app.json
的subpackages
字段声明项目分包结构 - 特点
- 加载小程序的时候先加载主包,当需要访问分包页面的时候才加载分包内容
- 分包的页面可以访问主包的文件,数据,图片等资源
- 开发者通过在
独立分包
在
app.json
的subpackages
字段当中的每一个配置项中添加independent
为true特点
- 独立分包可以单独访问分包的内容,不需要下载主包
- 独立分包不能依赖主包或者其他包的内容
独立分包使用场景
- 通常某些页面和当前小程序的其他页面关联不大的时候可以进行独立分包
- 比如: 临时加的广告页 或者是 活动页
使用常规分包的具体步骤和示例
1 | 打包之前的app.json的pages配置项 |
(1).为分包建立文件夹
1 | 这里就建立一个名字叫做mysubpackages文件夹 |
(2).将除了启动页(tabBar)的页面文件夹放置在刚刚创建的文件夹当中
- 注意,这里为了演示,其实应该将这里文件夹放置在pages文件夹下方的,也就是
/mysubpackages/pages
文件夹下方,和主包的目录结构保持一致的
(3).app.json配置项修改
app.json当中的pages配置项只留下主包
1 | "pages": [ |
将分包写入app.json当中的subpackages配置项
subpackages
中,每个分包的配置有以下几项:
1 | 字段 类型 说明 |
app.json当中subpackages配置项
1 | "subpackages": [ |
(4).更改跳转路径
1 | //跳转到搜索界面 |
(5).目录结构
分包预下载
微信小程序生命周期
- @官方API - 生命周期
- 复习下vue的生命周期
- beforeCreated,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed
- 小程序生命周期
- onLoad
- onShow(会重复出现)
- onReady
- onHide 路由重定向的时候如果选择了比如说
wx.navigatorTo
之类的保活的,就会产生隐藏生命周期 - onUnload 相当于是销毁的生命周期
- 具体的图片
小程序使用npm包步骤
(1).初始化
1 | npm init -y |
(2).勾选使用npm(有的项目需要勾选,现在没有这个选项了)
(3).下载需要的包
1 | npm install moment --save |
(4).引入包
1 | // pages/boundingClientRect/boundingClientRect.js |
(5).引入包后构建npm
- 开发工具 —> 工具 —> 构建npm
- 会将node_modules中的包打包到miniprogram_npm中
如果步骤错了,会报这个错误module 'pages/boundingClientRect/moment.js' is not defined, require args is 'moment''
只需要再次构建下npm就可以
- 注意
- 测试的时候引入
axios
包,然后按照这个流程发现不行,可能是小程序不支持axios
吧
- 测试的时候引入
小程序的ajax请求发送和二次封装
- @官方API - wx.request
- 需要注意的是
- 在h5的时候,全局对象为window,但是在微信小程序是没有window的,取而代之的全局对象是wx
- 所以是用
wx.xxxx
来调用微信提供的方法 - wx.request规定必须是https协议 ,最大并发为10
ajax请求发送
发送请求示例代码
1 | wx.request({ |
二次封装
1 | // 二次封装请求 |
小程序使用自定义组件
(1)建立文件夹
- 1.先依次建立一个文件夹叫
componets/NavHeader
(2)右键新建Component
- 2.1.在
NavHeader
文件夹右键,选中新建Component
,输入与文件夹同名的名称 - 2.2.
NavHeader
文件夹当中的结构和普通的页面结构一样,唯一不同的是不会自动在app.json当中的配置项pages中注册,因为不是页面嘛
(3)构建NavHeader的结构
3.1 书写NavHeader结构并使用
NavHeader.js
当中的propertyies属性
- 可以看到,选择
新建Component
生成的js文件会自动添加如下内容,我们使用的多的,就是properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33// components/NavHeader/NavHeader.js
Component({
/**
* 组件的属性列表
*/
properties: {
//书写自定义属性
title:{
//指明属性类型
type:String,
value:"未传入时候的默认值-title"
},
desc:{
type:String,
value:"未传入时候的默认值-desc"
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})- 可以看到,选择
3.2 在
NavHeader.wxml
中使用NavHeader.js
的properties属性
1
2
3
4
5<!--components/NavHeader/NavHeader.wxml-->
<view>
<text>标题:{{title}}</text>
<text>描述:{{desc}}</text>
</view>
(4)其他组件注册使用自定义组件
- 在要使用此组件的页面的xxx.json里面的配置项目
usingCompoents
去注册,比如下方的index.json当中注册使用组件NavHeader
index.json当中使用自定义组件NavHeader(相当于注册组件吧有点)
1 |
|
(5使用并传值
index.wxml中使用(也就是xxx.wxml中使用)
1 | <!-- 使用自定义组件 --> |
tabBar底部导航的实现
tabBar
配置项用的比较多的color
: tab 上的文字默认颜色,仅支持十六进制颜色selectedColor
:tab 上的文字选中时的颜色,仅支持十六进制颜色backgroundColor
:tab 的背景色,仅支持十六进制颜色list
: tab 的列表,详见list
属性说明,最少 2 个、最多 5 个 tab
注意的是
- 假如有需求需要计算一个容器的高度比如通过
calc
计算,那么在计算高度的时候,比如减去一部分的高度,这个时候可以忽略tabBar的高度,而不用减去,因为微信小程序会自动处理
- 假如有需求需要计算一个容器的高度比如通过
示例 app.json
当中添加配置项
1 | { |
效果图
js文件使用this.data.xxx和this.xxx和this.setData的区别
1 | // pages/test/test.js |
this.data.xxx
this.data.xxx
操作当前配置项当中data的属性值,但是操作不会更新视图
this.xxx
- 操作当前由Page生成的实例化对象上的属性
- 可以用来绑定一个共用,唯一的值,比如说单例
this.setData
this.setData({ value: 'leaf' })
可以更新配置项当中data的属性值,并且会引发视图更新
1 | this.setData({ |
元素当中id和data-xxx在辨别数据的使用
- 有时候我们想一个函数被二个不同功能的组件所触发,但是所处理的功能不同,就可以为组件添加id或者是data-xxx来区分
id
区分和data-xxx
区分主要区别就是id
只能有一个,而data-xxx
可以有多个- 在回调函数的事件对象当中通过
currentTarget
或者target
来获取id或者data-xxx属性- currentTarget和target的区别主要在于是否是事件委派,如果没有事件委派,那么二者没有区别
- 如果有事件委派/委托,区别如下
currentTarget
是绑定事件的元素(父元素)target
: 是触发事件的元素(子元素)
有如下结构
可以看到,test.wxml
的二个view组件都赋予了同一个回调函数,那么如何区分呢?这里添加了id
和data-index
1 | <!--pages/test/test.wxml--> |
test.js内容
1 | handleTouch(event){ |
我们任意单击一个view
,输出查看下事件对象event
,可以看到,currentTarget和target记录着一些数据,正好是我们所设置的数据,那么就可以以此来区分是哪一个组件触发的了
完整js代码如下
1 | handleTouch(event) { |
当然,也可以通过data-xxx
来区分
1 | handleTouch(event) { |
文本超出显示省略号或文本超出两行后显示省略号
- 需要注意的是
overflow
属性只会在块级元素才会生效
文本超出显示省略号
- 关键代码就是下面这三行
1 | white-space:nowrap; |
示例
1 |
|
文本超出两行后显示省略号
- 关键代码如下
1 | display: -webkit-box; |
示例
1 |
|
小程序的轻提示(Toast)
- @官方API - Toast
- 和其他不同的就是小程序的轻提示除了
none
,其他都只限于7个汉字的长度 - 并且小程序的轻提示-
wx.showLoading
必须要调用wx.hideToast
进行手动关闭才可以,其他的就不用
小程序当中视频的操作
想要操作视频,比如说跳转到指定位置,倍速播放的时候,就需要对视频(video)进行操作了
大致操作就是先创建属于这个视频的上下文对象,然后对上下文对象进行操作
- 设计到视频的操作有很多,可以查看官方API的说明~
bindtimeupdate
: 播放进度变化时触发bindfullscreenchange
: 视频进入和退出全屏时触发
下方步骤为操作一个video的基本步骤
(0)wxml基本结构
1 | <!--pages/videotest/videotest.wxml--> |
(1)创建视频上下文对象
- @官方API - createVideoContext
let 当前video的上下文对象 = wx.createVideoContext(video组件的id)
1 | // pages/videotest/videotest.js |
(2)控制视频的播放/暂停/跳转
1 | handlePlay() { |
补充:由于微信问题,视频播放下一个的时候不会自动暂停上一个视频,所以这里需要使用视频上下文进行处理
演示内容,当播放视频1的时候,又跑去播放视频2,那么视频1会被暂停播放
示例
wxml
基本结构- 记得绑定
bindplay
哦
- 记得绑定
1 | <!--pages/videotest/videotest.wxml--> |
js
代码
1 | handlePlay(event) { |
小程序的video组件设置为100%出现黑色边框
- @官方API - video
- 设置
video
组件的object-fit
属性为cover
即可
如图
scroll-view滚动到指定位置并且有过渡效果
- @官网API -scroll-view
- 实现滚动到指定位置的二个属性
scroll-into-view
: 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素scroll-with-animation
: 在设置滚动条位置时使用动画过渡
- 实现原理
- 通过动态设置
scroll-into-view
的值来实现
- 通过动态设置
效果
代码实现
wxml
1 | <!--pages/bar/bar.wxml--> |
js
1 | // pages/bar/bar.js |
wxss
1 | /* pages/bar/bar.wxss */ |
用户转发分享和自定义转发分享内容
如果想要区分是当前页面调用了button触发的分享还是右上角转发菜单触发的分享,只需要在onShareAppMessage
回调当中结构出from
,通过from判断
1 | onShareAppMessage({from}) { |
button实现
- 通过设置button的
open-type
属性为share,即成为了一个分享功能的按钮,其实这样子已经可以使用了,但是我们可以自定义分享的图片和标题~ - 想要自定义,就需要在对应页面的js文件当中添加
onShareAppMessage
回调 - @官网API-onShareAppMessage
wxml
1 | <!--pages/share/share.wxml--> |
js
1 | // pages/share/share.js |
自定义内容后的效果
微信小程序背景音频的播放
(1)获取全局唯一的背景音频管理对象,返回BackgroundAudioManager 实例
注意的是
从微信客户端6.7.2版本开始,若需要在小程序切后台后继续播放音频,需要在 app.json 中配置
requiredBackgroundModes
属性。开发版和体验版上可以直接生效,正式版还需通过审核。1
2
3
4
5{
"requiredBackgroundModes": [
"audio"
],
}
1 | onLoad(options) { |
(2)操作BackgroundAudioManager 实例
- @官方API - BackgroundAudioManager 实例
- 比较常用的实例属性
startTime
: 音频开始播放的位置(单位:s)。src
:音频的数据源(2.2.3 开始支持云文件ID)。默认为空字符串,当设置了新的 src 时,会自动开始播放,目前支持的格式有 m4a, aac, mp3, wav。title
:**(必填)**音频标题,用于原生音频播放器音频标题(必填)。原生音频播放器中的分享功能,分享出去的卡片标题,也将使用该值。duration
:当前音频的长度(单位:s),只有在有合法 src 时返回。(只读)currentTime
:当前音频的播放位置(单位:s),只有在有合法 src 时返回。(只读)
- 比较常用的方法
play()
: 播放音乐pause()
: 暂停音乐seek(跳转到的位置)
: 跳转到指定位置(单位为s)onTimeUpdate(callback)
:监听背景音频播放进度更新事件,只有小程序在前台时会回调。onEnded()
:监听背景音频自然播放结束事件
1 | onLoad(options) { |
微信小程序的授权登录和获取openid
wx.getUserProfile( 2022 年 10 月 25 日 24 时后 会失效)
(1).button按钮绑定回调
1 | <!--pages/userprofile/userprofile.wxml--> |
(2).自定义一个函数,这里取名 handleUserInfo 并且添加wx.getUserProfile方法 需要注意的是,事件名都是小写
1 | // pages/userprofile/userprofile.js |
(3).处理授权结果
- 成功结果输出
- 失败结果输出
1 | {errMsg: "getUserProfile:fail getUserProfile:fail auth deny"} |
获取openid
wx.login
与auth.code2Session
结合使用wx.login
- 调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台帐号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台帐号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。
auth.code2Session
步骤如下
(1).wx.login获取登录凭证
1 | handleOpenid() { |
(2).有了登录凭证,再通过auth.code2Session获取openid
- 这里我没有自己后台服务器,就直接这样子用了,其实可以通过后台来调用,这样子就不会泄露自己的开发信息了
1 | //获取openid |
(3).处理结果
- 授权成功输出
- 授权失败输出这里错误的appid
小程序更新数据状态的区别
- 实时更新(每发一次请求就更新一部分数据)
- 优点: 用户等待时间较短
- 缺点: 多次更新页面
1 | for(循环请求数据){ |
- 统一更新
- 优点: 减少更新的次数,只更新1次
- 缺点: 网络较差的时候用户等待时间过长,可能会看到白屏
1 | let 全部数据 ; |
小程序的数据存储
不同小程序的数据存储相互独立,互不干扰. @官方解释网站
同一个微信用户,同一个小程序 storage 上限为 10MB。storage 以用户维度隔离,同一台设备上,A 用户无法读取到 B 用户的数据;不同小程序之间也无法互相读写数据。
插件隔离策略
- 同一小程序使用不同插件:不同插件之间,插件与小程序之间 storage 不互通。
- 不同小程序使用同一插件:同一插件 storage 不互通。
与h5的storage不同的是,h5的需要转化为json格式的字符串后存储,而小程序可以直接存储对象,也可以存储json格式字符串
wx.setStorageSync(存数据)
- 将数据存储在本地缓存中指定的 key 中。会覆盖掉原来该 key 对应的内容。除非用户主动删除或因存储空间原因被系统清理,否则数据都一直可用。单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
示例 - 直接存储对象
1 | let data = { |
调试器信息 - Storage项
wx.getStorageSync(取数据)
1 | let data1 = wx.getStorageSync('userInfo'); |
调试器输出信息
小程序scroll-view的下拉刷新
- @官方API-scroll-view组件
- scroll-view需要开启和设置的属性
refresher-triggered
: 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发(会显示相应的效果)refresher-enabled
: 是否开启自定义下拉刷新,true开启,false关闭(默认)
- scroll-view需要添加的回调或监听
bindrefresherrefresh
:自定义下拉刷新被触发
- scroll-view需要实现上拉加载更多只需要添加
bindscrolltolower
滚动到底部/右边时触发就可以
- 顺带一提
- 使用
calc
计算scroll-view的高度的时候,calc的计算符号和数字之间必须要分开来才可以,否者计算会无效!并且如果小程序有tabBar(底部导航),可以不用减去底部导航的高度(小程序会自动处理)
- 使用
示例
- 模拟请求发送数据,1s后关闭下拉刷新并显示提示
效果图
wxml
1 | <!--pages/refreshscroll/refreshscroll.wxml--> |
js
1 | // pages/refreshscroll/refreshscroll.js |
wxss
1 | /* pages/refreshscroll/refreshscroll.wxss */ |
为什么小程序没有引入css样式都会生效?
在html开发的时候,我们会通过@import或者link标签来引入css文件,但是微信小程序却不用我们去引入,那是为什么?
我们在
app.json
的配置项pages
已经书写了一条,比如下面代码,我们知道,所有页面都需要写在pages
当中1
2
3
4
5
6{
"pages": [
"pages/index/index",
],
"sitemapLocation": "sitemap.json"
}在我们进入页面,比如说
index
页面的时候,小程序回去寻找pages/index
文件夹,然后依次访问,寻找与访问页面同名的文件,index.wxml,
index.wxss
,index.js
,index.json
- 所以你可以试试看,把
index.wxss
改为index11.wxss
,然后再去访问index
页面,就会丢失样式
- 所以你可以试试看,把
@import 和import 引入css区别和小程序引入css?
- 一句话@import引入css样式在html文件,或者css文件当中,
- 而import是用来引入模块的,当然,如果有webpack工具也是可以通过import引入css文件的
@import的用法
- (1) html当中的link标签中使用
1 | <link rel="stylesheet" type="text/css" href="css文件路径"/> |
- (2) html当中的style标签中使用
1 | <style type="text/css"> |
- (3) css文件当中引入
1 | @import url(css文件路径); |
@import区别
- link是XHTML标签,除了加载CSS外,还可以定义RRS等其他事务。@import属于CSS范畴,只能加载CSS
- link引用CSS样式,是和页面加载同步进行加载,@import是等页面加载完后才开始加载。
- link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
- link支持使用Javascript控制DOM去改变样式;而@import不支持。
小程序引入css
- @ 官方API - wxss
- 使用
@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束
示例
1 | /** app.wxss **/ |
微信小程序动态类(class)
- vue的时候动态类
1 | //vue代码 |
- 小程序的动态类
1 | <!--pages/classdongtai/classdongtai.wxml--> |
使用事件委托,children层存在嵌套时无法获取标识符id,非嵌套时可以如期获取,嵌套获取不到标识符id的解决办法
- 有人提出这个问题,然后我自己也遇到了这个问题,就来记录下
- 先说嵌套时候的解决办法
- 通过为子元素添加mark属性
- @官方API - mark属性
- mark属性简介
- 在基础库版本 2.7.1 以上,可以使用
mark
来识别具体触发事件的 target 节点。此外,mark
还可以用于承载一些自定义数据(类似于dataset
)。 - 当事件触发时,事件冒泡路径上所有的
mark
会被合并,并返回给事件回调函数。(即使事件不是冒泡事件,也会mark
。)
- 在基础库版本 2.7.1 以上,可以使用
委派子元素层存在嵌套获取不到标识符id的情况的演示
- 本来想通过事件委派,然后通过
event.target.id
来获取是哪一个元素所触发的,这样子方便寻找数据,但是实际情况却是,当单击到了子元素嵌套的元素的时候,就获取不到id
了
演示动画,可以看到,单击子元素内部的索引号或者邮箱地址的时候,出现获取不到id
的情况
委派子元素层存在嵌套获取id的办法-通过mark属性
实现代码
wxml
1 | <!--pages/weipaimark/weipaimark.wxml--> |
js
1 | handleClick(event){ |
wxss
1 | /* pages/weipaimark/weipaimark.wxss */ |
演示效果
其他知识点
js操作的键值为变量的时候,需要使用中括号
1 | // pages/refreshscroll/refreshscroll.js |
判断类型的时候,老师说最好是全等来判断
位移运算符转化为数字
- 这里使用无符号右移运算符转换为数字~
- 如果转换过程中有字母,则返回0
1 | var a = '12'; |
- 补充
!
一个感叹号表示取反!!
二个感叹号转化为布尔值!!!
三个感叹号表示转化为布尔值并取反
object的toString和Array的toString和其他的toString
toString()
函数的作用是返回object的字符串表示,JavaScript中object默认的toString()方法返回字符串[object Object]
。定义类时可以实现新的toString()方法,从而返回更加具有可读性的结果。JavaScript对于数组对象、函数对象、正则表达式对象以及Date日期对象均定义了更加具有可读性的toString()方法:
object的toSting(经常用来判断数据类型)
- 如果不是object,而是function,需要通过
Object.prototype.toSting.call()
来调用 - 通过toString()返回类型后可以通过
slice(8,-1)
来获取具体类型,代码功能为从索引为8的开始取,直到倒数第二个
1 | //object的toString |
array当中的toString
- array当中的toString会返回以逗号分割的字符串
1 | //array的toString |
函数的toString
- function的toString()方法将返回函数的文本定义
1 | //函数当中的toString |
Date的toString
- Date的toString()方法将返回一个具有可读性的日期时间字符串
1 | // Date的toString() |
正则的toString
- RegExp的toString()方法与function的toString()方法类似,将返回正则表达式的文本定义
1 | // RegExp的toString()方法 |
设计模式之单例模式,工厂模式简说
单例模式
- 创建多个对象的情况下,使用一个变量来保存,始终只有一个对象
- 当创建新的对象的时候就会把之前的对象覆盖掉
- 可以节省内存空间
工厂模式
- 根据不同的参数创建不同的对象
如果遍历的是数组里面的对象,那么修改遍历时候的遍历项,会影响原数组
代码示例如下,可以看到,更改了找到的item项目后,原来的也会改变
1 | const array1 = [{ |
数组的includes,indexOf,find,findIndex ,concat ,slice,splice
includes
includes()
方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回true
,否则返回false
。
1 | const array1 = [1, 2, 3]; |
indexOf
indexOf()
方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
1 | const beasts = ['ant', 'bison', 'camel', 'duck', 'bison']; |
find
- 方法返回数组中满足提供的测试函数的第一个元素的值,找到后就会停止查找,否则返回
undefined
。
1 | const array1 = [5, 12, 8, 130, 44]; |
findIndex
findIndex()
方法返回数组中满足提供的测试函数的第一个元素的索引,找到后就会停止查找,若没有找到对应元素则返回-1。
1 | const array1 = [5, 12, 8, 130, 44]; |
concat
concat()
方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
1 | const array1 = ['a', 'b', 'c']; |
slice
slice()
方法返回一个新的数组对象,这一对象是一个由begin
和end
决定的原数组的浅拷贝(包括begin
,不包括end
)相当于左闭右开。原始数组不会被改变。
1 | const animals = ['ant', 'bison', 'camel', 'duck', 'elephant']; |
splice
splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
1 | const months = ['Jan', 'March', 'April', 'June']; |
calc计算高度时候的一个坑,因为符号问题
- 错误的写法,运算符和操作数之间没有空格分开
1 | .video-scroll{ |
- 正确的写法,运算符和操作数之间用空格分开
1 | .video-scroll{ |
display:flex和float不能同时使用!!!因为display:flex开启后是内容撑开容器,float就无法浮动了,因为没有位置了
开启定位后子元素相当于父元素水平垂直居中
- 原理可以看看这@文章
- 简单来说就是盒子计算的问题
1 | <!DOCTYPE html> |
设置旋转的中心点
参考的文章1 https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
参考的文章2 http://www.360doc.com/content/20/0710/23/25947829_923464975.shtml
在没有设置旋转中心的时候,我们设置
transform:rotate(45deg);
都是围绕元素中点来旋转的,如下图
但是有时候我们需要设置旋转中心,就需要通过
transform-origin
来设置了- 比如transform-origin:50px 50px,意思就是将中心点移动到距离容器x轴
50px
的位置,y轴50px
的位置
- 比如transform-origin:50px 50px,意思就是将中心点移动到距离容器x轴
也可以设置为右上角顶点
transform-origin:0 0
- 旋转动画
transform-origin:0 0
并设置transform:rotate(45deg)
效果
小程序生命周期的onLoad当中的参数options,用于路由传参
- 原生小程序url有长度限制,如果传参内容过长会自动截取掉
- options.id可以传入的id参数
在组件 wxss 中不应使用 ID 选择器、属性选择器和标签名选择器。
如题~