Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
uni-app
提交
80b31809
U
uni-app
项目概览
DCloud
/
uni-app
4 个月 前同步成功
通知
730
Star
38707
Fork
3642
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
7
列表
看板
标记
里程碑
合并请求
1
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
7
Issue
7
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
80b31809
编写于
9月 02, 2020
作者:
inkwalk
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add: uni.createMediaQueryObserver Api and mediaQueryObserver Object
上级
7e31ef7d
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
302 addition
and
10 deletion
+302
-10
docs/api/ui/mediaQuery-observer.md
docs/api/ui/mediaQuery-observer.md
+134
-0
lib/apis.js
lib/apis.js
+1
-0
lib/modules.json
lib/modules.json
+6
-5
src/core/service/api/ui/create-media-query-observer.js
src/core/service/api/ui/create-media-query-observer.js
+47
-0
src/core/service/bridge/subscribe.js
src/core/service/bridge/subscribe.js
+18
-0
src/core/service/plugins/index.js
src/core/service/plugins/index.js
+6
-2
src/core/service/plugins/polyfill.js
src/core/service/plugins/polyfill.js
+5
-1
src/core/view/bridge/subscribe/api/index.js
src/core/view/bridge/subscribe/api/index.js
+9
-2
src/core/view/bridge/subscribe/api/request-media-query-observer.js
...view/bridge/subscribe/api/request-media-query-observer.js
+76
-0
未找到文件。
docs/api/ui/mediaQuery-observer.md
0 → 100644
浏览文件 @
80b31809
节点布局交叉状态 API 可用于监听两个或多个组件节点在布局位置上的相交状态。这一组API常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。
### uni.createIntersectionObserver([this], [options])
创建并返回一个
``IntersectionObserver``
对象实例。
**this说明:**
自定义组件实例。
**支付宝小程序不支持此参数,传入仅为抹平写法差异**
**options 的可选参数为:**
|字段名|类型|说明|
|:-|:-|:-|
|thresholds|Array|一个数值数组,包含所有阈值。默认为
``[0]``
。|
|initialRatio|Number|初始的相交比例,如果调用时检测到的相交比例与这个值不相等且达到阈值,则会触发一次监听器的回调函数。默认为
``0``
。|
|observeAll|Boolean|是否同时观测多个参照节点(而非一个),如果设为
``true``
,
``observe``
的
``targetSelector``
将选中多个节点(注意:同时选中过多节点将影响渲染性能)|
### IntersectionObserver 对象的方法列表
|方法|说明|
|:-|:-|
|IntersectionObserver.relativeTo(selector,[margins])|使用选择器指定一个节点,作为参照区域之一。|
|IntersectionObserver.relativeToViewport([margins])|指定页面显示区域作为参照区域之一|
|IntersectionObserver.observe(selector,[callback])|指定目标节点并开始监听相交状态变化情况。回调函数
``callback``
包含一个参数
``result``
|
|IntersectionObserver.disconnect()|停止监听。回调函数将不再触发。|
**margins 参数:**
用来扩展(或收缩)参照节点布局区域的边界。
|属性|类型|默认值|是否必填|说明|
|:-|:-|:-|:-|:-|
|left|number||否|节点布局区域的左边界|
|right|number||否|节点布局区域的右边界|
|top|number||否|节点布局区域的上边界|
|bottom|number||否|节点布局区域的下边界|
下面的示例代码中,如果目标节点
``".test"``
进入
``".scroll"``
区域以下 100px 时,就会触发回调函数。
```
uni.createIntersectionObserver(this).relativeTo('.scroll',{bottom: 100}).observe('.test', (res) => {
console.log(res);
})
```
**observe 回调函数 result 包含的字段**
|字段名|类型|说明|
|:-|:-|:-|
|intersectionRatio|Number|相交比例|
|intersectionRect|Object|相交区域的边界,包含
``left``
、
``right``
、
``top``
、
``bottom``
四项|
|boundingClientRect|Object|目标节点布局区域的边界,包含
``left``
、
``right``
、
``top``
、
``bottom``
四项|
|relativeRect|Object|参照区域的边界,包含
``left``
、
``right``
、
``top``
、
``bottom``
四项|
|time|Number|相交检测时的时间戳|
**Tips**
-
与页面显示区域的相交区域并不准确代表用户可见的区域,因为参与计算的区域是“布局区域”,布局区域可能会在绘制时被其他节点裁剪隐藏(如祖先节点中 overflow 样式为 hidden 的节点)或遮盖(如 fixed 定位的节点)。
-
节点交互状态
``API``
建议在
``onReady``
生命周期里监听,因为此
``API``
需要查找页面元素,
``onReady``
时页面已经完成初次渲染,已经能查找到对应的元素。
### 代码示例
```
<template>
<view class="container">
<text>{{appear ? '小球出现' : '小球消失'}}</text>
<view class="page-section">
<scroll-view class="scroll-view" scroll-y>
<view class="scroll-area">
<text class="notice">向下滚动让小球出现</text>
<view class="ball"></view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
let observer = null;
export default {
data() {
return {
appear: false
}
},
onReady() {
observer = uni.createIntersectionObserver(this);
observer.relativeTo('.scroll-view').observe('.ball', (res) => {
if (res.intersectionRatio > 0 && !this.appear) {
this.appear = true;
} else if (!res.intersectionRatio > 0 && this.appear) {
this.appear = false;
}
})
},
onUnload() {
if (observer) {
observer.disconnect()
}
}
}
</script>
<style>
view,page {
display: flex;
flex-direction: column;
}
.scroll-view {
height: 400rpx;
background: #fff;
border: 1px solid #ccc;
box-sizing: border-box;
}
.scroll-area {
height: 1300rpx;
display: flex;
flex-direction: column;
align-items: center;
transition: .5s;
}
.notice {
margin-top: 150rpx;
margin: 150rpx 0 400rpx 0;
}
.ball {
width: 200rpx;
height: 200rpx;
background: #1AAD19;
border-radius: 50%;
}
</style>
```
lib/apis.js
浏览文件 @
80b31809
...
...
@@ -161,6 +161,7 @@ const ui = [
'
stopPullDownRefresh
'
,
'
createSelectorQuery
'
,
'
createIntersectionObserver
'
,
'
createMediaQueryObserver
'
,
'
getMenuButtonBoundingClientRect
'
]
...
...
lib/modules.json
浏览文件 @
80b31809
...
...
@@ -113,15 +113,15 @@
"uni.getBLEDeviceServices"
:
true
,
"uni.getBLEDeviceCharacteristics"
:
true
,
"uni.createBLEConnection"
:
true
,
"uni.closeBLEConnection"
:
true
,
"uni.setBLEMTU"
:
true
,
"uni.closeBLEConnection"
:
true
,
"uni.setBLEMTU"
:
true
,
"uni.getBLEDeviceRSSI"
:
true
,
"uni.onBeaconServiceChange"
:
true
,
"uni.onBeaconUpdate"
:
true
,
"uni.getBeacons"
:
true
,
"uni.startBeaconDiscovery"
:
true
,
"uni.stopBeaconDiscovery"
:
true
,
"uni.onThemeChange"
:
true
,
"uni.stopBeaconDiscovery"
:
true
,
"uni.onThemeChange"
:
true
,
"uni.onUIStyleChange"
:
true
}
},
{
...
...
@@ -157,7 +157,8 @@
"uni.stopPullDownRefresh"
:
true
,
"uni.createSelectorQuery"
:
true
,
"uni.createIntersectionObserver"
:
true
,
"uni.hideKeyboard"
:
true
,
"uni.createMediaQueryObserver"
:
true
,
"uni.hideKeyboard"
:
true
,
"uni.onKeyboardHeightChange"
:
true
}
},
{
...
...
src/core/service/api/ui/create-media-query-observer.js
0 → 100644
浏览文件 @
80b31809
import
createCallbacks
from
'
uni-helpers/callbacks
'
import
{
getCurrentPageVm
}
from
'
../../platform
'
const
createMediaQueryObserverCallbacks
=
createCallbacks
(
'
requestMediaQueryObserver
'
)
class
ServiceMediaQueryObserver
{
constructor
(
component
,
options
)
{
this
.
pageId
=
component
.
$page
.
id
this
.
component
=
component
.
_$id
||
component
// app-plus 平台传输_$id
this
.
options
=
options
}
observe
(
options
,
callback
)
{
if
(
typeof
callback
!==
'
function
'
)
{
return
}
this
.
options
=
options
this
.
reqId
=
createMediaQueryObserverCallbacks
.
push
(
callback
)
UniServiceJSBridge
.
publishHandler
(
'
requestMediaQueryObserver
'
,
{
reqId
:
this
.
reqId
,
component
:
this
.
component
,
options
:
this
.
options
},
this
.
pageId
)
}
disconnect
()
{
UniServiceJSBridge
.
publishHandler
(
'
destroyMediaQueryObserver
'
,
{
reqId
:
this
.
reqId
},
this
.
pageId
)
}
}
export
function
createMediaQueryObserver
(
context
,
options
)
{
if
(
!
context
.
_isVue
)
{
options
=
context
context
=
null
}
if
(
context
)
{
return
new
ServiceMediaQueryObserver
(
context
,
options
)
}
return
new
ServiceMediaQueryObserver
(
getCurrentPageVm
(
'
createMediaQueryObserver
'
),
options
)
}
src/core/service/bridge/subscribe.js
浏览文件 @
80b31809
...
...
@@ -50,6 +50,23 @@ export default function initSubscribe (subscribe, {
}
}
const
requestMediaQueryObserverCallbacks
=
createCallbacks
(
'
requestMediaQueryObserver
'
)
function
onRequestMediaQueryObserver
({
reqId
,
reqEnd
,
res
})
{
const
callback
=
requestMediaQueryObserverCallbacks
.
get
(
reqId
)
if
(
callback
)
{
if
(
reqEnd
)
{
requestMediaQueryObserverCallbacks
.
pop
(
reqId
)
return
}
callback
(
res
)
}
}
if
(
__PLATFORM__
===
'
h5
'
)
{
subscribe
(
'
onPageReady
'
,
createPageEvent
(
'
onReady
'
))
}
...
...
@@ -59,4 +76,5 @@ export default function initSubscribe (subscribe, {
subscribe
(
'
onRequestComponentInfo
'
,
onRequestComponentInfo
)
subscribe
(
'
onRequestComponentObserver
'
,
onRequestComponentObserver
)
subscribe
(
'
onRequestMediaQueryObserver
'
,
onRequestMediaQueryObserver
)
}
src/core/service/plugins/index.js
浏览文件 @
80b31809
...
...
@@ -73,7 +73,7 @@ export default {
initPolyfill
(
Vue
)
lifecycleMixin
(
Vue
)
/* eslint-disable no-undef */
if
(
typeof
__UNI_ROUTER_BASE__
!==
'
undefined
'
)
{
__uniConfig
.
router
.
base
=
__UNI_ROUTER_BASE__
...
...
@@ -194,7 +194,11 @@ export default {
return
uni
.
createIntersectionObserver
(
this
,
args
)
}
Vue
.
prototype
.
createMediaQueryObserver
=
function
createMediaQueryObserver
(
args
)
{
return
uni
.
createMediaQueryObserver
(
this
,
args
)
}
Vue
.
use
(
VueRouter
)
}
}
}
src/core/service/plugins/polyfill.js
浏览文件 @
80b31809
...
...
@@ -70,6 +70,10 @@ export function initPolyfill (Vue) {
return
uni
.
createIntersectionObserver
(
this
,
options
)
}
Vue
.
prototype
.
createMediaQueryObserver
=
function
createMediaQueryObserver
(
options
)
{
return
uni
.
createMediaQueryObserver
(
this
,
options
)
}
Vue
.
prototype
.
selectComponent
=
function
selectComponent
(
selector
)
{
return
querySelector
(
this
,
parseSelector
(
selector
))
}
...
...
@@ -77,4 +81,4 @@ export function initPolyfill (Vue) {
Vue
.
prototype
.
selectAllComponents
=
function
selectAllComponents
(
selector
)
{
return
querySelectorAll
(
this
,
parseSelector
(
selector
),
[])
}
}
}
src/core/view/bridge/subscribe/api/index.js
浏览文件 @
80b31809
...
...
@@ -11,9 +11,16 @@ import {
destroyComponentObserver
}
from
'
./request-component-observer
'
import
{
requestMediaQueryObserver
,
destroyMediaQueryObserver
}
from
'
./request-media-query-observer
'
export
default
{
setPageMeta
,
requestComponentInfo
,
requestComponentObserver
,
destroyComponentObserver
}
destroyComponentObserver
,
requestMediaQueryObserver
,
destroyMediaQueryObserver
}
src/core/view/bridge/subscribe/api/request-media-query-observer.js
0 → 100644
浏览文件 @
80b31809
const
mediaQueryObservers
=
{}
const
listeners
=
{}
// 用公用对象存储监听器
// 拼接媒体查询条件
function
handleMediaQueryStr
(
$props
)
{
let
mediaQueryStr
=
[]
const
propsMenu
=
[
'
width
'
,
'
minWidth
'
,
'
maxWidth
'
,
'
height
'
,
'
minHeight
'
,
'
maxHeight
'
,
'
orientation
'
]
for
(
const
item
of
propsMenu
)
{
if
(
item
!==
'
orientation
'
&&
$props
[
item
]
!==
''
&&
Number
(
$props
[
item
])
>=
0
)
{
mediaQueryStr
.
push
(
`(
${
humpToLine
(
item
)}
:
${
Number
(
$props
[
item
])}
px)`
)
}
if
(
item
===
'
orientation
'
&&
$props
[
item
])
{
mediaQueryStr
.
push
(
`(
${
humpToLine
(
item
)}
:
${
$props
[
item
]}
)`
)
}
}
mediaQueryStr
=
mediaQueryStr
.
join
(
'
and
'
)
return
mediaQueryStr
}
function
humpToLine
(
name
)
{
return
name
.
replace
(
/
([
A-Z
])
/g
,
'
-$1
'
).
toLowerCase
()
}
// 请求媒体查询对象
export
function
requestMediaQueryObserver
({
reqId
,
options
},
pageId
)
{
const
pages
=
getCurrentPages
()
const
page
=
pages
.
find
(
page
=>
page
.
$page
.
id
===
pageId
)
if
(
!
page
)
{
throw
new
Error
(
`Not Found:Page[
${
pageId
}
]`
)
}
const
pageVm
=
page
.
$vm
// 创建一个媒体查询对象
const
mediaQueryObserver
=
mediaQueryObservers
[
reqId
]
=
window
.
matchMedia
(
handleMediaQueryStr
(
options
))
// 创建一个监听器
const
listener
=
listeners
[
reqId
]
=
e
=>
{
UniViewJSBridge
.
publishHandler
(
'
onRequestMediaQueryObserver
'
,
{
reqId
,
res
:
e
.
matches
},
pageVm
.
$page
.
id
)
}
listener
(
mediaQueryObserver
)
// 监听前执行一次媒体查询
mediaQueryObserver
.
addListener
(
listener
)
}
// 销毁媒体查询对象
export
function
destroyMediaQueryObserver
({
reqId
})
{
const
listener
=
listeners
[
reqId
]
// 需要移除的某个监听
const
mediaQueryObserver
=
mediaQueryObservers
[
reqId
]
if
(
mediaQueryObserver
)
{
mediaQueryObserver
.
removeListener
(
listener
)
// 移除监听
delete
mediaQueryObservers
[
reqId
]
UniViewJSBridge
.
publishHandler
(
'
onRequestMediaQueryObserver
'
,
{
reqId
,
reqEnd
:
true
})
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录