一、view组件及其重要属性
view最主要的功能是布局
1.1 相关属性
属性1:hover-class 指定按下去的样式类
这个属性指定按下去的类样式,让容器有一个单击效果,
当hover-class="none"时,或者没有设置这个属性时,就没有单击态的效果。
单击、再松开手指之后,容器组件恢复之前的状态。
<view hover-class="bc_red" class="section__title">content</view>
hover-class 这个属性名称有一定的迷惑性,
在HTML开发中,mousehover事件指的是鼠标悬停事件,hover有悬停的意思,mousedown才是鼠标按下去的事件。
属性2:hover-stop-propagation 组织父节点出现单击态,
默认为false,不阻止
hover-stop-propagation="{{false}}"
单击子组件的时候,父组件同时也有了一个样式的改变。
hover-stop-propagation
子容器有单击态,父容器没有,
虽然父容器也设置了hover-class属性,
但触碰事件被子容器给阻止了。
事件三阶段
我们通过跟踪父子组件的tap事件,验证一下hover-stop-propagation属性的作用。
在示例中我们给两个view,一对父子容器同时绑定tap事件,
为方便追踪,为父子容器都分配了id,父容器id是parentView,子容器是childView。
单击一次父容器,输出一次。
单击一次子容器却输出两次。
为什么会触发两次的tap事件?
这是因为每个事件它都有捕捉、目标与冒泡三个阶段,
在view视图容器上使用bind绑定的事件,
默认会在目标与冒泡这两个阶段派发事件,
子组件的冒泡事件默认会向上传递。
hover-stop-propagation这个属性
就是为了阻止父组件出现hover-class样式,
但是它还不能阻止冒泡事件向上传递、
当我们设置这个属性以后,
我们单击子组件,仍然可以看到两次输出。
那么我们可以让子容器view的tap事件只派发一次吗
?
答案是肯定的,可以使用catch绑定事件函数,
catch与bind的作用相同,
与bind不同的是:
catch会阻止事件向上冒泡。
catch是在事件的捕捉阶段监听事件的。
将子容器的bindtap改为catchtap
,
这样单击子容器组件的时候便不会输出两次了。
<!-- 事件三阶段-->
<view id="parentView" bindtap="onTap" hover-class="bc_red" class="section__title">
parent
<view id="childView" bindtap="onTap" hover-stop-propagation hover-class="bc_green" class="section__title">
child view
</view>
</view>
<!-- 5 子组件只输出一次-->
<!-- 阻止父节点出现hover状态,阻止冒泡 -->
<view id="parentView" bindtap="onTap" hover-class="bc_red" class="section__title">
parent
<view id="childView" catchtap="onTap" hover-stop-propagation hover-class="bc_green" class="section__title">
child view
</view>
</view>
onTap(e){
console.log(e.target)
}
属性3 :hover-start-time 按住后多久出现单击态 默认为50毫秒
设置hover-start-time这个属性,是为了方便开发者控制hover-class样式出现的时机。
属性4 :hover-stay-time 手指松开以后,单击态保留多长时间,单位均是毫秒
这两个属性的设置,说明在view容器组件内部,有代码肯定做了定时,
当touchstart事件发生时,开始计时,达到hover-start-time时,应用hover-class样式,
当touchstart事件结束,即touchend事件发生时,开始hover-stay-time的倒计时,时间到则移除hover-class样式。
1.2 了解苹果手机网页上为什么有300毫秒的延迟
当延迟超过100毫秒的时候,用户就会感觉到界面有明显的卡顿,
但是在移动设备上,特别是苹果的Safari浏览器上,我们不得不忍受300毫秒的延迟。
这是为什么呢?
2007年乔布斯在iphone发布会上演示这样一个功能,
对于一个Safari浏览器,在内容区快速单击,
苹果会帮助我们准确定位到文章的主题内容,并将其放大。
如果用户不小心在双击时,击到了一个链接,是马上跳转呢,还是等待用户的另外一次单击。
不然没办法判断它是不是双击事件。
苹果采用的是第二种方式,所有的Safari中的链接都要延迟300毫秒,
用这种方式观察用户是不是还要发出第二次单击事件,
如果没有,在跳转链接,这导致苹果手机中的HTML网页里面的单击反应都有一点的迟钝。
但是在微信小程序里,没有这个问题,hover-start-time默认时间是50毫秒,
只需要50毫秒,甚至更短的时间,就可以触发单击事件。
微信小程序已经迈过了300毫秒延迟的限制。
使用微信小程序开发产品
,相比HTML5有什么优势
?没有单击延迟
,这就是在体验上一个很大的优势。
拒绝300毫秒延迟
1.3 hover-class的应用
使用hover-class定义按钮状态
1.4 相关问题
hover-start-time属性的值,最小可以设置为多少,
设置为1毫秒,可以吗?为什么?
答案是可以设置了,但是设置了也没有效果,因为在小程序当中,
所有界面效果都受限于小程序本身的渲染帧率,每秒渲染60帧,每帧用时大概17毫秒,
所以设置成1毫秒或者17毫秒,它的效果是一样的,没有区别。
二、flex布局中常用的样式及样式值
- justify-content 调整内容在主轴方向的排列方式,
- align-items 对齐元素在辅轴方向的对齐方式
- align-content 对齐多行内容在辅轴方向上的排列方式
- flex-direction
2.1 相关问题
如何把view上的内容绘制到画布上,生成一张海报?
解决方案:
2.1.1 在这里有一个开源的小程序组件 Painter,封装了通过JSON数据绘制海报的功能,
- 安装
- 1.https://github.com/Kujiale-Mobile/Painter 下载组件painter
- 2.放在components文件夹下
- 3.在JSON 组件声明
{
"usingComponents":
{
"painter":"../../components/painter/painter",
}
}
- 使用
1.pages/index
index.wxml
<view class="section">
生成分享图,将view转绘为图片
<button type="primary" class="intro" open-type="getUserInfo" bindgetuserinfo="getUserInfo" wx:if="{{!nickName}}">获取分享图头像昵称</button>
<button type="primary" class="intro" bindtap="createShareImage" wx:else>点我生成分享图</button>
<share-box isCanDraw="{{isCanDraw}}" bind:initData="createShareImage" />
</view>
index.js
//painter生成海报
Page({
data: {
nickName: '',
avatarUrl: '',
isCanDraw: false
},
onLoad() {
this.setData({
nickName: wx.getStorageSync('nickName') || '',
avatarUrl: wx.getStorageSync('avatarUrl') || ''
})
},
getUserInfo(e) {
this.setData({
nickName: e.detail.userInfo.nickName,
avatarUrl: e.detail.userInfo.avatarUrl
})
wx.setStorageSync('avatarUrl', e.detail.userInfo.avatarUrl)
wx.setStorageSync('nickName', e.detail.userInfo.nickName)
},
createShareImage() {
this.setData({
isCanDraw: !this.data.isCanDraw
})
},
})
index.json
{
"usingComponents": {
"share-box": "../../components/shareBox/index",
}
}
2.components/shareBox pages/index/index.wxml index.js
isCanDraw drawPic
imgDraw sharePath
- 效果
2.1.2 或者使用weui中的wxml-to-canvas
- 安装
- 1.npm install --save wxml-to-canvas
- 2.点击小程序开发工具的工具–构建npm
- 3.JSON 组件声明
{
"usingComponents": {
"wxml-to-canvas": "wxml-to-canvas",
}
}
- 使用
index.wxml
<!-- wxml-to-canvas weui生成海报 start -->
<!-- wxml -->
<view class="page-section">
<view class="page-section-title">wxml</view>
<view class="container">
<view class="item-box red">
</view>
<view class="item-box green">
<text class="text">yeah!</text>
</view>
<view class="item-box blue">
<image class="img"
src="https://cdn.nlark.com/yuque/0/2020/png/1252071/1590050624644-dd5948db-22fe-48d9-af37-8a2a9f099715.png">
</image>
</view>
</view>
</view>
<!-- -->
<!-- 渲染wxml -->
<view class="page-section">
<view class="page-section-title">渲染wxml</view>
组件
<wxml-to-canvas class="widget"></wxml-to-canvas>
<view class="page-section-title">导出图片</view>
图片
<image src="{{src}}" style="width: {{width}}px; height: {{height}}px"></image>
</view>
<!-- btns -->
<view class="btn-area">
<button type="primary" bindtap="renderToCanvas">渲染到canvas</button>
<button bindtap="extraImage">导出图片</button>
<button bindtap="onTapSaveBtn">保存图片</button>
</view>
<!-- wxml-to-canvas end -->
index.js
//wxml-to-canvas weui生成海报
const { wxml, style } = require('./demo')
Page({
data: {
src: ''
},
onLoad() {
this.widget = this.selectComponent('.widget')
},
onTapSaveBtn(e){
wx.saveImageToPhotosAlbum({
filePath:this.data.src,
complete(res) {
console.log(res)
}
})
},
renderToCanvas() {
const p1 = this.widget.renderToCanvas({ wxml, style })
p1.then((res) => {
console.log('container', res.layoutBox)
this.container = res
})
},
extraImage() {
const p2 = this.widget.canvasToTempFilePath()
p2.then(res => {
this.setData({
src: res.tempFilePath,
width: this.container.layoutBox.width,
height: this.container.layoutBox.height
})
})
}
})
demo.js
const wxml = `
<view class="container" >
<view class="item-box red">
</view>
<view class="item-box green" >
<text class="text">yeah!</text>
</view>
<view class="item-box blue">
<image class="img" src="https://cdn.nlark.com/yuque/0/2020/png/1252071/1590050624644-dd5948db-22fe-48d9-af37-8a2a9f099715.png"></image>
</view>
</view>
`
const style = {
container: {
width: 300,
height: 200,
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: '#ccc',
alignItems: 'center',
},
itemBox: {
width: 80,
height: 60,
},
red: {
backgroundColor: '#ff0000'
},
green: {
backgroundColor: '#00ff00'
},
blue: {
backgroundColor: '#0000ff',
alignItems: 'center',
justifyContent: 'center',
},
text: {
width: 80,
height: 60,
textAlign: 'center',
verticalAlign: 'middle',
},
img: {
width: 40,
height: 40,
borderRadius: 20,
}
}
module.exports = {
wxml,
style
}
index.scss
/* wxml-to-canvas weui生成海报 */
.widget {
}
.container {
width: 300px;
height: 200px;
min-height: 200px;
flex-direction: row;
justify-content: space-around;
background-color: #ccc;
align-items: center;
padding: 60px 0 60px;
display: flex;
}
.item-box {
width: 80px;
height: 60px;
display: flex;
}
.red{
background-color: #ff0000
}
.green {
background-color: #00ff00
}
.blue{
background-color: #0000ff;
align-items: center;
justify-content: center;
}
.text{
width: 80px;
height: 60px;
text-align: center;
vertical-align: middle;
line-height: 60px;
}
.img{
width: 40px;
height: 40px;
border-radius: 50%;
}
- 效果
- bug
- 关于 Cancvas API 错误:createImage fail: http://tmp/xxx…png
index.js use2dCanvas
index.js _drawImage
index.js isTempFile isNetworkFile
- 不随滚动的页面滚动与基础库有关系