From 284dba4d20954dae7a20dc12e64708e2d393c4fc Mon Sep 17 00:00:00 2001
From: rex <rexkaneki@gmail.com>
Date: Thu, 7 May 2020 14:50:21 +0800
Subject: [PATCH] feat(sticky): add new prop scroll-top

fix #3114
---
 example/pages/sticky/index.js   | 20 +++++++++++--
 example/pages/sticky/index.wxml | 17 +++++++++++
 example/project.config.json     |  7 +++++
 packages/mixins/page-scroll.ts  | 12 ++++----
 packages/sticky/README.md       | 53 +++++++++++++++++++++++++++++----
 packages/sticky/index.ts        |  9 ++++++
 6 files changed, 104 insertions(+), 14 deletions(-)

diff --git a/example/pages/sticky/index.js b/example/pages/sticky/index.js
index fa5c1540..07c72027 100644
--- a/example/pages/sticky/index.js
+++ b/example/pages/sticky/index.js
@@ -2,12 +2,26 @@ import Page from '../../common/page';
 
 Page({
   data: {
-    container: null
+    container: null,
+    scrollTop: 0,
+    offsetTop: 0,
   },
 
   onReady() {
     this.setData({
-      container: () => wx.createSelectorQuery().select('#container')
+      container: () => wx.createSelectorQuery().select('#container'),
     });
-  }
+  },
+
+  onScroll(event) {
+    wx.createSelectorQuery()
+      .select('#scroller')
+      .boundingClientRect((res) => {
+        this.setData({
+          scrollTop: event.detail.scrollTop,
+          offsetTop: res.top,
+        });
+      })
+      .exec();
+  },
 });
diff --git a/example/pages/sticky/index.wxml b/example/pages/sticky/index.wxml
index a432ba46..f8bf6599 100644
--- a/example/pages/sticky/index.wxml
+++ b/example/pages/sticky/index.wxml
@@ -23,3 +23,20 @@
     </van-sticky>
   </view>
 </demo-block>
+
+<demo-block title="嵌套在 scroll-view 内使用">
+  <scroll-view
+    bind:scroll="onScroll"
+    scroll-y
+    id="scroller"
+    style="height: 200px; background-color: #fff;"
+  >
+    <view style="height: 400px; padding-top: 50px;">
+      <van-sticky scroll-top="{{ scrollTop }}" offset-top="{{ offsetTop }}">
+        <van-button type="warning">
+          嵌套在 scroll-view 内
+        </van-button>
+      </van-sticky>
+    </view>
+  </scroll-view>
+</demo-block>
diff --git a/example/project.config.json b/example/project.config.json
index cb5b51bc..78e2d532 100644
--- a/example/project.config.json
+++ b/example/project.config.json
@@ -348,6 +348,13 @@
 					"id": -1,
 					"name": "calendar",
 					"pathName": "pages/calendar/index",
+					"query": "",
+					"scene": null
+				},
+				{
+					"id": -1,
+					"name": "index-bar",
+					"pathName": "pages/index-bar/index",
 					"scene": null
 				}
 			]
diff --git a/packages/mixins/page-scroll.ts b/packages/mixins/page-scroll.ts
index babddcc2..5c13597c 100644
--- a/packages/mixins/page-scroll.ts
+++ b/packages/mixins/page-scroll.ts
@@ -27,10 +27,10 @@ export const pageScrollMixin = (scroller: Scroller) =>
       if (Array.isArray(page.vanPageScroller)) {
         page.vanPageScroller.push(scroller.bind(this));
       } else {
-        page.vanPageScroller = [
-          page.onPageScroll.bind(page),
-          scroller.bind(this)
-        ];
+        page.vanPageScroller =
+          typeof page.onPageScroll === 'function'
+            ? [page.onPageScroll.bind(page), scroller.bind(this)]
+            : [scroller.bind(this)];
       }
 
       page.onPageScroll = onPageScroll;
@@ -39,7 +39,7 @@ export const pageScrollMixin = (scroller: Scroller) =>
     detached() {
       const page = getCurrentPage();
       page.vanPageScroller = (page.vanPageScroller || []).filter(
-        item => item !== scroller
+        (item) => item !== scroller
       );
-    }
+    },
   });
diff --git a/packages/sticky/README.md b/packages/sticky/README.md
index 40770f0f..aa242dcc 100644
--- a/packages/sticky/README.md
+++ b/packages/sticky/README.md
@@ -66,15 +66,58 @@ Page({
 });
 ```
 
+### 嵌套在 scroll-view 内使用
+
+通过 `scroll-top` 与 `offset-top` 属性可以实现在 scroll-view 内嵌套使用
+
+```html
+<scroll-view
+  bind:scroll="onScroll"
+  scroll-y
+  id="scroller"
+  style="height: 200px;"
+>
+  <view style="height: 400px; padding-top: 50px;">
+    <van-sticky scroll-top="{{ scrollTop }}" offset-top="{{ offsetTop }}">
+      <van-button type="warning">
+        嵌套在 scroll-view 内
+      </van-button>
+    </van-sticky>
+  </view>
+</scroll-view>
+```
+
+```js
+Page({
+  data: {
+    scrollTop: 0,
+    offsetTop: 0,
+  },
+
+  onScroll(event) {
+    wx.createSelectorQuery()
+      .select('#scroller')
+      .boundingClientRect((res) => {
+        this.setData({
+          scrollTop: event.detail.scrollTop,
+          offsetTop: res.top,
+        });
+      })
+      .exec();
+  },
+});
+```
+
 ## API
 
 ### Props
 
-| 参数       | 说明                                   | 类型       | 默认值 |
-| ---------- | -------------------------------------- | ---------- | ------ |
-| offset-top | 吸顶时与顶部的距离,单位`px`           | _number_   | `0`    |
-| z-index    | 吸顶时的 z-index                       | _number_   | `99`   |
-| container  | 一个函数,返回容器对应的 NodesRef 节点 | _function_ | -      |
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| offset-top | 吸顶时与顶部的距离,单位`px` | _number_ | `0` |
+| z-index | 吸顶时的 z-index | _number_ | `99` |
+| container | 一个函数,返回容器对应的 NodesRef 节点 | _function_ | - |
+| scroll-top | 当前滚动区域的滚动位置,非 `null` 时会禁用页面滚动事件的监听 | _number_ | - |
 
 ### Events
 
diff --git a/packages/sticky/index.ts b/packages/sticky/index.ts
index 6724da6c..3230ad27 100644
--- a/packages/sticky/index.ts
+++ b/packages/sticky/index.ts
@@ -24,10 +24,19 @@ VantComponent({
       type: null,
       observer: 'onScroll',
     },
+    scrollTop: {
+      type: null,
+      observer(val) {
+        this.onScroll({ scrollTop: val });
+      },
+    },
   },
 
   mixins: [
     pageScrollMixin(function (event) {
+      if (this.data.scrollTop != null) {
+        return;
+      }
       this.onScroll(event);
     }),
   ],