第二章:微信小程序组件介绍及使用 (43讲)
07 | icon组件:关于图标的4个实现方案
组件属性的长度单位默认为px,2.4.0起支持传入单位(rpx/px)。
| 属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
|---|---|---|---|---|---|
| type | string | 是 | icon的类型,有效值:success, success_no_circle, info, warn, waiting, cancel, download, search, clear | 1.0.0 | |
| size | number/string | 23 | 否 | icon的大小 | 1.0.0 |
| color | string | 否 | icon的颜色,同css的color | 1.0.0 |
实现方式
- 图片
- 背景图片(网络图片)
- css绘制
- 字体图标
08 | progress组件:如何自定义实现一个环形进度条?
09 | rich-text组件:如何单击预览rich-text中的图片并保存?
| 属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
|---|---|---|---|---|---|
| nodes | array/string | [] | 否 | 节点列表/HTML String | 1.4.0 |
| space | string | 否 | 显示连续空格 | 2.4.1 |
- 开源组件 mp-html
10 | view容器组件及Flex布局(一):学习容器组件view及其重要属性
| 属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
|---|---|---|---|---|---|
| hover-class | string | none | 否 | 指定按下去的样式类。当 hover-class="none" 时,没有点击态效果 | 1.0.0 |
| hover-stop-propagation | boolean | false | 否 | 指定是否阻止本节点的祖先节点出现点击态 | 1.5.0 |
| hover-start-time | number | 50 | 否 | 按住后多久出现点击态,单位毫秒 | 1.0.0 |
| hover-stay-time | number | 400 | 否 | 手指松开后点击态保留时间,单位毫秒 | 1.0.0 |
11 | view容器组件及Flex布局(二):介绍flex布局中常用的样式及样式值
一、Flex 布局是什么?
Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为 Flex 布局。
.box{
display: flex;
}
行内元素也可以使用 Flex 布局。
.box{
display: inline-flex;
}
Webkit 内核的浏览器,必须加上-webkit前缀。
.box{
display: -webkit-flex; /* Safari */
display: flex;
}
注意,设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效。
二、基本概念
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。
三、容器的属性
以下6个属性设置在容器上。
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
3.1 flex-direction属性
flex-direction属性决定主轴的方向(即项目的排列方向)。
.box {
flex-direction: row | row-reverse | column | column-reverse;
}
它可能有4个值。
row(默认值):主轴为水平方向,起点在左端。row-reverse:主轴为水平方向,起点在右端。column:主轴为垂直方向,起点在上沿。column-reverse:主轴为垂直方向,起点在下沿。
3.2 flex-wrap属性
默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行。
.box{
flex-wrap: nowrap | wrap | wrap-reverse;
}
它可能取三个值。
(1)nowrap(默认):不换行。
(2)wrap:换行,第一行在上方。
(3)wrap-reverse:换行,第一行在下方。
3.3 flex-flow
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}
3.4 justify-content属性
justify-content属性定义了项目在主轴上的对齐方式。
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
它可能取5个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。
flex-start(默认值):左对齐flex-end:右对齐center: 居中space-between:两端对齐,项目之间的间隔都相等。space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
3.5 align-items属性
align-items属性定义项目在交叉轴上如何对齐。
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
}
它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。
flex-start:交叉轴的起点对齐。flex-end:交叉轴的终点对齐。center:交叉轴的中点对齐。baseline: 项目的第一行文字的基线对齐。stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
3.6 align-content属性
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
该属性可能取6个值。
flex-start:与交叉轴的起点对齐。flex-end:与交叉轴的终点对齐。center:与交叉轴的中点对齐。space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch(默认值):轴线占满整个交叉轴。
四、项目的属性
以下6个属性设置在项目上。
orderflex-growflex-shrinkflex-basisflexalign-self
4.1 order属性
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
.item {
order: <integer>;
}
4.2 flex-grow属性
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
.item {
flex-grow: <number>; /* default 0 */
}
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
4.3 flex-shrink属性
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
.item {
flex-shrink: <number>; /* default 1 */
}
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
负值对该属性无效。
4.4 flex-basis属性
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
.item {
flex-basis: <length> | auto; /* default auto */
}
它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。
4.5 flex属性
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
4.6 align-self属性
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
该属性可能取6个值,除了auto,其他都与align-items属性完全一致。
12 | 可移动容器及可移动区域(一):学习使用movable-view与movable-area组件
13 | 可移动容器及可移动区域(二):如何实现侧滑删除功能
14 | scroll-view介绍:在小程序中如何实现滚动锚定?
| 属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 | ||
|---|---|---|---|---|---|---|---|
| scroll-x | boolean | false | 否 | 允许横向滚动 | 1.0.0 | ||
| scroll-y | boolean | false | 否 | 允许纵向滚动 | 1.0.0 | ||
| upper-threshold | number/string | 50 | 否 | 距顶部/左边多远时,触发 scrolltoupper 事件 | 1.0.0 | ||
| lower-threshold | number/string | 50 | 否 | 距底部/右边多远时,触发 scrolltolower 事件 | 1.0.0 | ||
| scroll-top | number/string | 否 | 设置竖向滚动条位置 | 1.0.0 | |||
| scroll-left | number/string | 否 | 设置横向滚动条位置 | 1.0.0 | |||
| scroll-into-view | string | 否 | 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 | 1.0.0 | |||
| scroll-with-animation | boolean | false | 否 | 在设置滚动条位置时使用动画过渡 | 1.0.0 | ||
| enable-back-to-top | boolean | false | 否 | iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向 | 1.0.0 | ||
| enable-flex | boolean | false | 否 | 启用 flexbox 布局。开启后,当前节点声明了 display: flex 就会成为 flex container,并作用于其孩子节点。 | 2.7.3 | ||
| scroll-anchoring | boolean | false | 否 | 开启 scroll anchoring 特性,即控制滚动位置不随内容变化而抖动,仅在 iOS 下生效,安卓下可参考 CSS overflow-anchor 属性。 | 2.8.2 | ||
| refresher-enabled | boolean | false | 否 | 开启自定义下拉刷新 | 2.10.1 | ||
| refresher-threshold | number | 45 | 否 | 设置自定义下拉刷新阈值 | 2.10.1 | ||
| refresher-default-style | string | "black" | 否 | 设置自定义下拉刷新默认样式,支持设置 `black | white | none`, none 表示不使用默认样式 | 2.10.1 |
| refresher-background | string | "#FFF" | 否 | 设置自定义下拉刷新区域背景颜色 | 2.10.1 | ||
| refresher-triggered | boolean | false | 否 | 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发 | 2.10.1 | ||
| enhanced | boolean | false | 否 | 启用 scroll-view 增强特性 | 2.12.0 | ||
| bounces | boolean | true | 否 | iOS 下 scroll-view 边界弹性控制 (同时开启 enhanced 属性后生效) | 2.12.0 | ||
| show-scrollbar | boolean | true | 否 | 滚动条显隐控制 (同时开启 enhanced 属性后生效) | 2.12.0 | ||
| paging-enabled | boolean | false | 否 | 分页滑动效果 (同时开启 enhanced 属性后生效) | 2.12.0 | ||
| fast-deceleration | boolean | false | 否 | 滑动减速速率控制 (同时开启 enhanced 属性后生效) | 2.12.0 | ||
| binddragstart | eventhandle | 否 | 滑动开始事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft } | 2.12.0 | |||
| binddragging | eventhandle | 否 | 滑动事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft } | 2.12.0 | |||
| binddragend | eventhandle | 否 | 滑动结束事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft, velocity } | 2.12.0 | |||
| bindscrolltoupper | eventhandle | 否 | 滚动到顶部/左边时触发 | 1.0.0 | |||
| bindscrolltolower | eventhandle | 否 | 滚动到底部/右边时触发 | 1.0.0 | |||
| bindscroll | eventhandle | 否 | 滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY} | 1.0.0 | |||
| bindrefresherpulling | eventhandle | 否 | 自定义下拉刷新控件被下拉 | 2.10.1 | |||
| bindrefresherrefresh | eventhandle | 否 | 自定义下拉刷新被触发 | 2.10.1 | |||
| bindrefresherrestore | eventhandle | 否 | 自定义下拉刷新被复位 | 2.10.1 | |||
| bindrefresherabort | eventhandle | 否 | 自定义下拉刷新被中止 | 2.10.1 |
15 | scroll-view介绍:如果渲染一个滚动的长列表?
<wxs module="refresh">
var pullingMessage = "下拉刷新"
module.exports = {
onRefresh: function(e, instance) {
// 此时手拉开了,进入了加载中的状态
pullingMessage = "更新中"
console.log(pullingMessage)
instance.callMethod("setData", {
pullingMessage: pullingMessage,
refresherTriggered: true
})
instance.callMethod("willCompleteRefresh", {})
},
onAbort: function(e, instance) {
// 异常状态,例如被事件突然打断,事件包括电话等,被迫松手了
pullingMessage = "下拉刷新"
console.log(pullingMessage)
},
onRestore: function(e, instance) {
// 回去了,松手了,恢复原位了,不刷了
pullingMessage = "下拉刷新"
console.log(pullingMessage)
},
onPulling: function(e, instance) {
// 80的高度,因为refresher-threshold设置的是80,手指按住往下拉的状态
var p = Math.min(e.detail.dy / 80, 1)
// console.log(p)
// 这里在视图层,不怕频繁操作DOM
var icon = instance.selectComponent('#refresherIcon')
icon.setStyle({
opacity: p,
transform: "rotate(" + (90 + p * 180) + "deg)"
})
var view = instance.selectComponent('.refresh-container')
view.setStyle({
opacity: p,
transform: "scale(" + p + ")"
})
if (e.detail.dy >= 80) {
if (pullingMessage == "下拉刷新") {
pullingMessage = "释放更新"
instance.callMethod("setData", {
pullingMessage
})
}
}
}
}
</wxs>
<scroll-view scroll-y
style="width: 100%; height: 400px;overflow-anchor:auto;"
bindscroll="onScroll"
bindscrolltoupper="onScrolltoupper"
scroll-top="{{scrollTopValue}}"
scroll-into-view="{{scrollIntoViewId}}"
scroll-with-animation
enable-back-to-top
enable-flex
scroll-anchoring
refresher-enabled
refresher-threshold="{{80}}"
refresher-default-style="none"
refresher-background="#FFF"
bindrefresherpulling="{{refresh.onPulling}}"
bindrefresherrefresh="{{refresh.onRefresh}}"
bindrefresherrestore="{{refresh.onRestore}}"
bindrefresherabort="{{refresh.onAbort}}"
refresher-triggered="{{refresherTriggered}}"
>
<view slot="refresher" class="refresh-container" style="display: block; width: 100%; height: 80px; background: #F8f8f8; display: flex; align-items: center;">
<view class="view1" style="position: absolute; text-align: center; width: 100%;display:flex;align-items:center;justify-content:center;color:#888;">
<mp-icon id="refresherIcon" icon="arrow" color="#888" size="{{20}}" style="margin-right:5px;transform:rotate(90deg)"></mp-icon>
<text style="min-width:80px;text-align:left;">{{pullingMessage}}</text>
</view>
</view>
<view wx:for="{{arr}}" id="view{{item+1}}" style="display: flex;height: 100px;">
<text style="position:relative;top:5px;left:5px;color:black;">{{item+1}}</text>
<image src="https://cdn.nlark.com/yuque/0/2020/jpeg/1252071/1586359160786-8d5b7738-3ad3-43e7-bf0a-738c58365645.jpeg"></image>
<image src="https://cdn.nlark.com/yuque/0/2020/jpeg/1252071/1586359160786-8d5b7738-3ad3-43e7-bf0a-738c58365645.jpeg"></image>
<image src="https://cdn.nlark.com/yuque/0/2020/jpeg/1252071/1586359160786-8d5b7738-3ad3-43e7-bf0a-738c58365645.jpeg"></image>
<image src="https://cdn.nlark.com/yuque/0/2020/jpeg/1252071/1586359160786-8d5b7738-3ad3-43e7-bf0a-738c58365645.jpeg"></image>
<image src="https://cdn.nlark.com/yuque/0/2020/jpeg/1252071/1586359160786-8d5b7738-3ad3-43e7-bf0a-738c58365645.jpeg"></image>
</view>
</scroll-view>
const app = getApp()
let viewId = 5
Page({
data: {
arr: [],
triggered: false,
scrollTopValue: 0,
scrollIntoViewId: '',
pullingMessage: '下拉刷新', //下拉刷新,释放更新,加新中...
refresherTriggered: false, //
tabs: []
},
willCompleteRefresh() {
console.log('更新中')
let intervalId = setInterval(() => {
let pullingMessage = this.data.pullingMessage
console.log(pullingMessage, pullingMessage == '更新中')
if (pullingMessage.length < 7) {
pullingMessage += '.'
} else {
pullingMessage = '更新中'
}
this.setData({
pullingMessage
})
}, 500)
setTimeout(() => {
console.log('更新完成了')
clearInterval(intervalId)
this.setData({
pullingMessage: "已刷新",
refresherTriggered: false,
})
}, 2000)
},
unshiftOnePic() {
let arr = this.data.arr
arr.unshift(arr.length + 1)
this.setData({
arr
})
},
scrollToView1() {
viewId += 2
this.setData({
scrollIntoViewId: 'childview' + viewId
})
console.log(this.data.scrollIntoViewId)
},
onReady: function () {
var ctx = createRecycleContext({
id: 'recycleId',
dataKey: 'recycleList',
page: this,
itemSize: {
width: rpx2px(650),
height: rpx2px(100)
}
})
let newList = []
for (let i = 0; i < 20; i++) {
newList.push({
id: i,
name: `标题${i + 1}`
})
}
ctx.append(newList)
//
const arr = []
for (let i = 0; i < 20; i++) arr.push(i)
this.setData({
arr
})
setTimeout(() => {
this.setData({
triggered: true,
})
}, 1000)
//
let activeTab = 0,
page = 1,
res = {
something: ''
}
let tabsData = this.data.tabs[activeTab] || {
list: []
}
tabsData.page = page + 1
tabsData.list.push(res)
let key = `tabs[${activeTab}]`
this.setData({
[key]: tabsData
})
console.log(this.data.tabs)
},
onPulling(e) {
console.log('onPulling:', e)
},
onRefresh() {
if (this._freshing) return
this._freshing = true
setTimeout(() => {
this.setData({
triggered: false,
})
this._freshing = false
}, 3000)
},
onRestore(e) {
console.log('onRestore:', e)
},
onAbort(e) {
console.log('onAbort', e)
},
onScroll(e) {
console.log(e.detail.scrollTop, e.detail.scrollLeft, e.detail.scrollHeight, e.detail.scrollWidth)
},
onScrolltoupper(e) {
console.log('已达顶部后,小于50,是一种状态')
},
plusScrollUpValue() {
this.setData({
scrollTopValue: this.data.scrollTopValue + 50
})
},
viewScrollToUpperEvent(e) {
console.log('测试scrolltoupper事件', e.detail);
}
})
16 | 滚动选择器(一):学习使用选择器组件
Component({
behaviors: ['wx://form-field'],
options: {
addGlobalClass: true,
},
properties: {
extClass: {type: String, value: ''},
name: {type: String, value: ''},
value: {type: String, value: ''},
options: {type: Array, value: []},
labelField: {type: String, value: 'label'},
valueField: {type: String, value: 'value'},
},
data: {
optionsArray: [],
currentIndex: 0,
},
observers: {
'value,options': function () {
this.getCurrentIndex();
this.getOptionsArray();
},
},
methods: {
bindChange: function (e) {
const index = e.detail.value;
if (index > -1) {
const value = this.data.options[index][this.data.valueField];
this.setData({
currentIndex: index,
value: value
});
let eventDetail = {
value: value
}
this.triggerEvent('change', eventDetail, {})
}
},
getOptionsArray() {
let array = this.data.options.map(v => {
return v[this.data.labelField];
});
this.setData({optionsArray: array})
},
getCurrentIndex() {
let index = this.data.options.findIndex(v => {
return v[this.data.valueField] === this.data.value;
})
this.setData({currentIndex: index})
}
}
})
<picker bindchange="bindChange"
value="{{currentIndex}}"
range="{{optionsArray}}"
>
<input type="text"
class="weui-input {{extClass}}"
value="{{optionsArray[currentIndex]}}"
placeholder="请选择"
disabled="{{true}}"
/>
<input type="text"
class="hidden"
name="{{name}}"
model:value="{{value}}"
/>
</picker>
17 | 滚动选择器(二):使用两种方式自定义实现省、市、区三级联动的选择器
以下是通过 picker 实现
const {area} = require('../../components/picker-area/area');
const getAreaById = (id) => {
return area[id] || []
}
Component({
options: {
addGlobalClass: true,
},
properties: {
extClass: {type: String, value: ''},
prov: {type: String, value: ''},
city: {type: String, value: ''},
dist: {type: String, value: ''},
},
data: {
multiArray: [],
objectMultiArray: [],
multiIndex: [0, 0, 0],
multiText: [],
},
lifetimes: {
attached: function () {
const provArray = getAreaById("prov");
const cityArray = getAreaById(provArray[0].value);
const distArray = getAreaById(cityArray[0].value);
this.getMultiArray(provArray, cityArray, distArray);
}
},
observers: {
'prov': function (prov) {
if (prov) {
const {prov, city, dist} = this.data;
const provArray = getAreaById("prov");
const cityArray = getAreaById(prov);
const distArray = getAreaById(city);
let multiIndex = [];
let multiText = [];
provArray.forEach((v, i) => {
if (v.value === prov) {
multiIndex.push(i);
multiText.push(v.label);
}
})
cityArray.forEach((v, i) => {
if (v.value === city) {
multiIndex.push(i);
multiText.push(v.label);
}
})
distArray.forEach((v, i) => {
if (v.value === dist) {
multiIndex.push(i);
multiText.push(v.label);
}
})
this.getMultiArray(provArray, cityArray, distArray);
this.setData({
multiIndex,
multiText
});
} else {
this.setData({
multiText: []
})
}
},
},
methods: {
getMultiArray(provArray, cityArray, distArray) {
const multiArray = [
provArray.map(v => v.label),
cityArray.map(v => v.label),
distArray.map(v => v.label),
];
const objectMultiArray = [provArray, cityArray, distArray];
this.setData({
multiArray,
objectMultiArray
});
},
bindMultiPickerChange: function (e) {
const multiIndex = e.detail.value;
const {multiArray, objectMultiArray} = this.data;
let multiText = [];
let multiValue = [];
for (let i = 0; i < 3; i++) {
if (multiArray[i][multiIndex[i]]) {
multiText.push(multiArray[i][multiIndex[i]]);
}
if (objectMultiArray[i][multiIndex[i]]) {
multiValue.push(objectMultiArray[i][multiIndex[i]]);
}
}
this.setData({
multiIndex,
multiText
});
let eventDetail = {
value: multiValue
};
this.triggerEvent('change', eventDetail, {})
},
bindMultiPickerColumnChange: function (e) {
const {multiIndex, objectMultiArray} = this.data;
let provArray = objectMultiArray[0];
let cityArray = objectMultiArray[1];
let distArray = objectMultiArray[2];
let column = e.detail.column;
let index = e.detail.value;
if (column === 0) {
cityArray = getAreaById(provArray[index].value);
distArray = getAreaById(cityArray[0].value);
this.setData({
multiIndex: [index, 0, 0]
})
} else if (column === 1) {
distArray = getAreaById(cityArray[index].value);
this.setData({
multiIndex: [multiIndex[0], index, 0]
})
}
this.getMultiArray(provArray, cityArray, distArray);
}
}
})
<picker mode="multiSelector"
bindchange="bindMultiPickerChange"
bindcolumnchange="bindMultiPickerColumnChange"
value="{{multiIndex}}"
range="{{multiArray}}"
>
<input type="text"
class="weui-input {{extClass}}"
value="{{multiText}}"
placeholder="请选择"
disabled="{{true}}"
/>
</picker>
module.exports.area = {
"110000": [
{"label": "市辖区", "value": "110100"},
{"label": "县", "value": "110200"}
],
"110100": [
{"label": "东城区", "value": "110101"},
{"label": "西城区", "value": "110102"},
{"label": "崇文区", "value": "110103"},
{"label": "宣武区", "value": "110104"},
{"label": "朝阳区", "value": "110105"},
{"label": "丰台区", "value": "110106"},
{"label": "石景山区", "value": "110107"},
{"label": "海淀区", "value": "110108"},
{"label": "门头沟区", "value": "110109"},
{"label": "房山区", "value": "110111"},
{"label": "通州区", "value": "110112"},
{"label": "顺义区", "value": "110113"},
{"label": "昌平区", "value": "110114"},
{"label": "大兴区", "value": "110115"},
{"label": "怀柔区", "value": "110116"},
{"label": "平谷区", "value": "110117"}
],
......
}
18 | 滑动选择器表单组件:如何基于wxs自定义一个竖向的slider?
19 | 页面链接组件:如何自定义一个导航栏?
{
"usingComponents": {
"navigation-bar":"/components/navigation-bar/index"
},
"navigationStyle": "custom"
}
// 该示例来源于https://developers.weixin.qq.com/community/develop/article/doc/00048e5ed784b037b959757385b413
// 有少量修改
Page({
data: {
loading: false,
active: true
},
//点击back事件处理
goBack: function () {
wx.navigateBack();
this.triggerEvent('back');
},
//返回首页
goHome: function () {
wx.reLaunch({
url: '/pages/index/index'
})
},
onPageScroll(res) {
console.log(res);
if (res.scrollTop > 400) {
if (!this.data.active) {
this.setData({
active: true
})
}
} else {
if (this.data.active) {
this.setData({
active: false
})
}
}
}
})
<navigation-bar
ext-class="page-navigator-bar"
active="{{active}}"
loading="{{loading}}">
<view class="left" slot="left">
<icon bindtap="goBack" class="iconfont icon-back"></icon>
<icon bindtap="goHome" class="iconfont icon-home"></icon>
</view>
<view slot="center">
<view>自定义导航标题</view>
</view>
</navigation-bar>
20 | image媒体组件(上):如何实现图片的懒加载?
-
mina-lazy-image
小程序图片懒加载自定义组件
背景
小程序原生图片组件 image 提供的图片懒加载功能
lazy-load限制过多,只针对 page 与 scroll-view 下的 image 有效。实现思路
使用
wx.createIntersectionObserver()判断图片是否出现在视口中并进行加载使用方法
- 安装组件
npm install --save mina-lazy-image- 在页面的 json 配置文件中添加 mina-lazy-image
使用此组件需要依赖小程序基础库 2.2.2 版本,同时依赖开发者工具的 npm 构建。具体详情可查阅官方 npm 文档。
{ "usingComponents": { "mina-lazy-image": "mina-lazy-image/index" } }-
WXML 文件中引用 mina-lazy-image
<mina-lazy-image src="{{src}}" mode="widthFIx" image-class="custom-class-name"/>mina-lazy-image 的属性介绍如下:
字段名 类型 必填 描述 src String 是 图片链接 placeholder String 否 占位图片链接 mode String 否 请参考 image 组件 mode 属性 webp Number 否 请参考 image 组件 webp 属性 showMenuByLongpress Boolean 否 请参考 image 组件 show-menu-by-longpress 属性 styles String 否 设置图片样式 viewport Object 否 默认为 {bottom: 0},配置图片显示区域 mina-lazy-image 外部样式类
image-class`, `image-container-class
21 | image媒体组件(下):开发中经常遇到的问题?
22 | 如何实现直播间功能?(一):了解live-pusher、live-player组件的主要属性及使用限制
23 | 如何实现直播间功能?(二):如何开启、使用腾讯云的云直播功能
24 | 如何实现直播间功能?(三):安装与使用ffmepg,及使用ffmpeg进行推拉流验证
25 | 如何实现直播间功能?(四):使用live-pusher、live-player组件在小程序中实现直播功能
26 | 如何实现直播间功能?(五):同层渲染
27 | 如何实现直播间功能?(六):live-pusher、live-player组件在开发中的常见问题
28 | web-view(一):了解session、cookie等相关基本概念
web-view
基础库 1.6.4 开始支持,低版本需做兼容处理。
承载网页的容器。会自动铺满整个小程序页面,个人类型的小程序暂不支持使用。
客户端 6.7.2 版本开始,navigationStyle: custom 对 web-view 组件无效
小程序插件中不能使用。
| 属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
|---|---|---|---|---|---|
| src | string | 否 | webview 指向网页的链接。可打开关联的公众号的文章,其它网页需登录小程序管理后台配置业务域名。 | 1.6.4 | |
| bindmessage | eventhandler | 否 | 网页向小程序 postMessage 时,会在特定时机(小程序后退、组件销毁、分享)触发并收到消息。e.detail = { data },data是多次 postMessage 的参数组成的数组 | 1.6.4 | |
| bindload | eventhandler | 否 | 网页加载成功时候触发此事件。e.detail = { src } | 1.6.4 | |
| binderror | eventhandler | 否 | 网页加载失败的时候触发此事件。e.detail = { src } | 1.6.4 |
相关接口 1
web-view网页中可使用JSSDK 1.3.2提供的接口返回小程序页面。 支持的接口有:
| 接口名 | 说明 | 最低版本 |
|---|---|---|
| wx.miniProgram.navigateTo | 参数与小程序接口一致 | 1.6.4 |
| wx.miniProgram.navigateBack | 参数与小程序接口一致 | 1.6.4 |
| wx.miniProgram.switchTab | 参数与小程序接口一致 | 1.6.5 |
| wx.miniProgram.reLaunch | 参数与小程序接口一致 | 1.6.5 |
| wx.miniProgram.redirectTo | 参数与小程序接口一致 | 1.6.5 |
| wx.miniProgram.postMessage | 向小程序发送消息,会在特定时机(小程序后退、组件销毁、分享)触发组件的message事件 | 1.7.1 |
| wx.miniProgram.getEnv | 获取当前环境 | 1.7.1 |
示例代码
// <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
// javascript
wx.miniProgram.navigateTo({url: '/path/to/page'})
wx.miniProgram.postMessage({ data: 'foo' })
wx.miniProgram.postMessage({ data: {foo: 'bar'} })
wx.miniProgram.getEnv(function(res) { console.log(res.miniprogram) })
29 | web-view(二):了解常见的四种鉴权方式
- Http Basic Authentication
- Session-Cookie
- Token
- OAuth