29 changed files with 473 additions and 308 deletions
Unified View
Diff Options
-
59components/_common/color.js
-
17components/_common/data-hook.js
-
9components/_common/extra-props.js
-
12components/_common/is-iphonex.js
-
24components/_common/jan-component.js
-
21components/_common/mixin-component.js
-
49components/_common/open-type.js
-
36components/_common/scroll-view.js
-
4components/_common/type-of.js
-
16components/_common/utils.wxs
-
56components/refresh-view/index.js
-
4components/refresh-view/index.json
-
9components/refresh-view/index.wxml
-
158components/refresh-view/index.wxs
-
68components/refresh-view/index.wxss
-
BINcomponents/refresher/.DS_Store
-
116components/refresher/index.js
-
5components/refresher/index.json
-
10components/refresher/index.wxml
-
33components/refresher/index.wxss
-
2pages/mall/index/index.json
-
2pages/mall/search-list/index.json
-
2pages/mall/shops/index.json
-
13pages/mall/shops/index.wxml
-
2pages/message/index.json
-
33pages/refresh/refresh.js
-
5pages/refresh/refresh.json
-
6pages/refresh/refresh.wxml
-
10pages/refresh/refresh.wxss
@ -0,0 +1,59 @@ |
|||||
|
const hex2Rgb = function(color) { |
||||
|
let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/ |
||||
|
color = color.toLowerCase() |
||||
|
if (color.length == 9) color = color.slice(0, 7) |
||||
|
if (reg.test(color)) { |
||||
|
if (color.length === 4) { |
||||
|
let colorNew = "#" |
||||
|
for (let i = 1; i < 4; i += 1) { |
||||
|
colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1)) |
||||
|
} |
||||
|
color = colorNew |
||||
|
} |
||||
|
let colorChange = [] |
||||
|
for (let i = 1; i < 7; i += 2) { |
||||
|
colorChange.push(parseInt("0x" + color.slice(i, i + 2))) |
||||
|
} |
||||
|
return colorChange |
||||
|
} else { |
||||
|
if (color.includes("rgb")) { |
||||
|
color = color |
||||
|
.replace(/(rgba|rgb)/, "") |
||||
|
.replace("(", "") |
||||
|
.replace(")", "") |
||||
|
|
||||
|
if (color.includes(",")) { |
||||
|
return color |
||||
|
.split(",") |
||||
|
.map(item => item * 1) |
||||
|
.slice(0, 3) |
||||
|
} else { |
||||
|
return [0, 0, 0] |
||||
|
} |
||||
|
} else { |
||||
|
return [0, 0, 0] |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const isTextDeepColor = function(backgroundRgbArr = [255, 255, 255]) { |
||||
|
if ( |
||||
|
!( |
||||
|
backgroundRgbArr instanceof Array && |
||||
|
backgroundRgbArr.length === 3 && |
||||
|
backgroundRgbArr.every(item => item >= 0 && item <= 255) |
||||
|
) |
||||
|
) |
||||
|
return false |
||||
|
|
||||
|
const grayLevel = |
||||
|
backgroundRgbArr[0] * 0.299 + |
||||
|
backgroundRgbArr[1] * 0.587 + |
||||
|
backgroundRgbArr[2] * 0.114 |
||||
|
return grayLevel >= 192 |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
hex2Rgb, |
||||
|
isTextDeepColor |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
const dataHook = function(dataList = [], hook) { |
||||
|
if ( |
||||
|
!dataList instanceof Array || |
||||
|
!dataList.length || |
||||
|
!dataList.every(item => typeof item == "string") |
||||
|
) |
||||
|
return {} |
||||
|
if (!hook instanceof Function) hook = () => void 0 |
||||
|
let obj = { |
||||
|
observers: {} |
||||
|
}, |
||||
|
key = dataList.join(",") |
||||
|
obj["observers"][key] = hook |
||||
|
return obj |
||||
|
} |
||||
|
|
||||
|
module.exports = dataHook |
||||
@ -0,0 +1,9 @@ |
|||||
|
const extraProps = function(props, extra) { |
||||
|
if (typeof extra !== "object") return props |
||||
|
for (let key in props) { |
||||
|
if (extra[key]) props[key] = extra[key] |
||||
|
} |
||||
|
return props |
||||
|
} |
||||
|
|
||||
|
module.exports = extraProps |
||||
@ -0,0 +1,12 @@ |
|||||
|
function isIphoneX() { |
||||
|
var systemInfo = wx.getSystemInfoSync() |
||||
|
return !!( |
||||
|
systemInfo && |
||||
|
systemInfo.model && |
||||
|
systemInfo.model.indexOf("iPhone X") > -1 |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
isIphoneX: isIphoneX |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
const mixinComponent = require("./mixin-component") |
||||
|
|
||||
|
const janComponent = function(options = {}) { |
||||
|
options = mixinComponent( |
||||
|
{ |
||||
|
options: { |
||||
|
addGlobalClass: true |
||||
|
}, |
||||
|
externalClasses: ["custom-class", "customClass"], |
||||
|
properties: { |
||||
|
customClass: String |
||||
|
}, |
||||
|
data: { |
||||
|
_class: "", |
||||
|
_style: "" |
||||
|
}, |
||||
|
methods: {} |
||||
|
}, |
||||
|
options |
||||
|
) |
||||
|
return options |
||||
|
} |
||||
|
|
||||
|
module.exports = janComponent |
||||
@ -0,0 +1,21 @@ |
|||||
|
const typeOf = require("./type-of") |
||||
|
|
||||
|
const mixinComponent = function(origin = {}, next = {}) { |
||||
|
if (typeOf(origin) !== "object") origin = {} |
||||
|
if (typeOf(next) !== "object") next = {} |
||||
|
|
||||
|
for (let key in next) { |
||||
|
if (typeOf(next[key]) === "object") { |
||||
|
if (typeOf(origin[key]) === "object") { |
||||
|
origin[key] = mixinComponent(origin[key], next[key]) |
||||
|
} else { |
||||
|
origin[key] = next[key] |
||||
|
} |
||||
|
} else { |
||||
|
if (typeOf(origin[key]) == "undefined") origin[key] = next[key] |
||||
|
} |
||||
|
} |
||||
|
return origin |
||||
|
} |
||||
|
|
||||
|
module.exports = mixinComponent |
||||
@ -0,0 +1,49 @@ |
|||||
|
const mapOpenType = function() { |
||||
|
return { |
||||
|
properties: { |
||||
|
openType: { |
||||
|
type: String, |
||||
|
value: "" |
||||
|
}, |
||||
|
id: String, |
||||
|
lang: { |
||||
|
type: String, |
||||
|
value: "en" |
||||
|
}, |
||||
|
businessId: Number, |
||||
|
sessionFrom: String, |
||||
|
sendMessageTitle: String, |
||||
|
sendMessagePath: String, |
||||
|
sendMessageImg: String, |
||||
|
showMessageCard: Boolean, |
||||
|
appParameter: String, |
||||
|
ariaLabel: String |
||||
|
}, |
||||
|
methods: { |
||||
|
$emit(type, e) { |
||||
|
this.triggerEvent(type, e) |
||||
|
}, |
||||
|
|
||||
|
bindGetUserInfo(event) { |
||||
|
this.$emit("getuserinfo", event.detail) |
||||
|
}, |
||||
|
bindContact(event) { |
||||
|
this.$emit("contact", event.detail) |
||||
|
}, |
||||
|
bindGetPhoneNumber(event) { |
||||
|
this.$emit("getphonenumber", event.detail) |
||||
|
}, |
||||
|
bindError(event) { |
||||
|
this.$emit("error", event.detail) |
||||
|
}, |
||||
|
bindLaunchApp(event) { |
||||
|
this.$emit("launchapp", event.detail) |
||||
|
}, |
||||
|
bindOpenSetting(event) { |
||||
|
this.$emit("opensetting", event.detail) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = mapOpenType |
||||
@ -0,0 +1,36 @@ |
|||||
|
const mapScrollView = function() { |
||||
|
return { |
||||
|
properties: { |
||||
|
scrollX: Boolean, |
||||
|
scrollY: { |
||||
|
type: Boolean, |
||||
|
value: true |
||||
|
}, |
||||
|
upperThreshold: { |
||||
|
type: Number, |
||||
|
value: 50 |
||||
|
}, |
||||
|
owerThreshold: { |
||||
|
type: Number, |
||||
|
value: 50 |
||||
|
}, |
||||
|
scrollTop: Number, |
||||
|
scrollLeft: Number, |
||||
|
scrollIntoView: String, |
||||
|
scrollWithAnimation: Boolean, |
||||
|
enableBackToTop: { |
||||
|
type: Boolean, |
||||
|
value: true |
||||
|
}, |
||||
|
enableFlex: Boolean, |
||||
|
scrollAnchoring: Boolean |
||||
|
}, |
||||
|
methods: { |
||||
|
$emit(type, e) { |
||||
|
this.triggerEvent(type, e) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = mapScrollView |
||||
@ -0,0 +1,4 @@ |
|||||
|
const typeOf = obj => |
||||
|
/\[object (.+?)\]/g.exec(Object.prototype.toString.call(obj))[1].toLowerCase() |
||||
|
|
||||
|
module.exports = typeOf |
||||
@ -0,0 +1,16 @@ |
|||||
|
function addUnit(value) { |
||||
|
if (value == null) { |
||||
|
return "" |
||||
|
} |
||||
|
|
||||
|
if (typeof value === "string" && value.indexOf("var") > -1) { |
||||
|
return value |
||||
|
} |
||||
|
|
||||
|
if (value >= 0) return value + "px" |
||||
|
return value |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
addUnit: addUnit |
||||
|
} |
||||
@ -1,56 +0,0 @@ |
|||||
// 使用的时候,用本组件包裹可以触发下拉刷新的内容。enablePullDownRefresh需要设置为false。
|
|
||||
Component({ |
|
||||
properties: { |
|
||||
refreshed: { // 必选,通知本组件收起
|
|
||||
type: Boolean, |
|
||||
value: false, |
|
||||
}, |
|
||||
refreshing: { // 可选,通知本组件直接进入refreshing状态
|
|
||||
type: Boolean, |
|
||||
value: false, |
|
||||
}, |
|
||||
distMax: { // 可选,可以下拉的最大高度,回弹的高度为最大高度的75%
|
|
||||
type: Number, |
|
||||
value: 45, |
|
||||
}, |
|
||||
color: { // 可选,圆弧颜色
|
|
||||
type: String, |
|
||||
value: "#000", |
|
||||
}, |
|
||||
backgroundColor: { // 可选,背景颜色
|
|
||||
type: String, |
|
||||
value: "#fff", |
|
||||
}, |
|
||||
type: { |
|
||||
type: Number, |
|
||||
value: 0 |
|
||||
} |
|
||||
}, |
|
||||
data: { |
|
||||
reachTop: false, |
|
||||
}, |
|
||||
methods: { |
|
||||
initObserver() { |
|
||||
this.observer = this.createIntersectionObserver() |
|
||||
this.observer.relativeToViewport().observe(".intersection-dot", (res) => { |
|
||||
if (res.intersectionRatio > 0) { |
|
||||
this.setData({ reachTop: true, }) |
|
||||
} else { |
|
||||
this.setData({ reachTop: false,}) |
|
||||
} |
|
||||
}) |
|
||||
}, |
|
||||
clearObserver() { |
|
||||
if (this.observer) { |
|
||||
this.observer.disconnect() |
|
||||
this.observer = null |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
ready() { |
|
||||
this.initObserver() |
|
||||
}, |
|
||||
detached() { |
|
||||
this.clearObserver() |
|
||||
}, |
|
||||
}) |
|
||||
@ -1,4 +0,0 @@ |
|||||
{ |
|
||||
"component": true, |
|
||||
"usingComponents": {} |
|
||||
} |
|
||||
@ -1,9 +0,0 @@ |
|||||
<wxs module="refresher" src="./index.wxs"></wxs> |
|
||||
<view class="refresh-wrap" style="{{backgroundColor ? 'background-color:' + backgroundColor + ';' : ''}}"> |
|
||||
<view class="refresh" style="{{color ? 'border-color:' + color + ';' : ''}}"></view> |
|
||||
</view> |
|
||||
<view class="wrap" change:refreshed="{{refresher.onRefreshed}}" refreshed="{{refreshed}}" change:refreshing="{{refresher.onRefreshing}}" refreshing="{{refreshing}}" data-dist-max="{{distMax}}" data-type="{{type}}" data-reach-top="{{reachTop}}" bind:touchstart="{{refresher.touchStart}}" |
|
||||
bind:touchmove="{{refresher.touchMove}}" bind:touchend="{{refresher.touchEnd}}"> |
|
||||
<view class="intersection-dot"></view> |
|
||||
<slot></slot> |
|
||||
</view> |
|
||||
@ -1,158 +0,0 @@ |
|||||
// 文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html |
|
||||
|
|
||||
/* eslint-disable */ |
|
||||
function calcResistance(distExtra, distMax) { |
|
||||
return Math.min(1, distExtra / distMax / 1.2) * Math.min(distMax, distExtra) |
|
||||
} |
|
||||
|
|
||||
function touchStart(e, ins) { |
|
||||
var dataset = e.instance.getDataset() |
|
||||
var state = e.instance.getState() |
|
||||
state.distMax = dataset.distMax |
|
||||
state.type = dataset.type |
|
||||
state.distThreshold = state.distMax * 0.75 |
|
||||
state.reachTop = dataset.reachTop |
|
||||
state.status = state.status || "pending" // pending、pulling、releasing、refreshing |
|
||||
|
|
||||
if (state.status === "pending" && state.reachTop) { |
|
||||
state.startPulling = true |
|
||||
state.pullStartX = e.touches[0].clientX |
|
||||
state.pullStartY = e.touches[0].clientY |
|
||||
state.distance = 0 |
|
||||
|
|
||||
state.component = state.component || ins.selectComponent(".refresh-wrap") |
|
||||
state.component.removeClass("transition") |
|
||||
state.component.removeClass("animation") |
|
||||
state.component.removeClass("fadeout") |
|
||||
state.component.setStyle({ |
|
||||
top: (state.distance * 2 - 20) + "rpx", |
|
||||
opacity: 0, |
|
||||
transform: "rotate(0)", |
|
||||
"-webkit-transform": "rotate(0)" |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function touchMove(e, ins) { |
|
||||
var state = e.instance.getState() |
|
||||
if (!state.startPulling || state.status === "refreshing") { |
|
||||
return true |
|
||||
} |
|
||||
state.pullMoveX = e.touches[0].clientX |
|
||||
state.pullMoveY = e.touches[0].clientY |
|
||||
if (state.status === "pending") { |
|
||||
state.status = "pulling" |
|
||||
} |
|
||||
var distExtraX = state.pullMoveX - state.pullStartX |
|
||||
var distExtraY = state.pullMoveY - state.pullStartY |
|
||||
if (distExtraY > 0 && Math.abs(distExtraY) >= Math.abs(distExtraX)) { |
|
||||
state.distance = calcResistance(distExtraY, state.distMax) |
|
||||
state.component.setStyle({ |
|
||||
top: setop(state.distance, state.type), |
|
||||
opacity: Math.min(1, state.distance / state.distThreshold), |
|
||||
transform: "rotate(" + (245 * state.distance / state.distMax) + "deg)", |
|
||||
"-webkit-transform": "rotate(" + (245 * state.distance / state.distMax) + "deg)" |
|
||||
}) |
|
||||
|
|
||||
if (state.status === "pulling" && state.distance > state.distThreshold) { |
|
||||
state.status = "releasing" |
|
||||
} |
|
||||
if (state.status === "releasing" && state.distance < state.distThreshold) { |
|
||||
state.status = "pulling" |
|
||||
} |
|
||||
return false |
|
||||
} |
|
||||
return true |
|
||||
} |
|
||||
|
|
||||
function touchEnd(e, ins) { |
|
||||
var state = e.instance.getState() |
|
||||
|
|
||||
if (!state.startPulling || state.status === "refreshing") { |
|
||||
return |
|
||||
} |
|
||||
state.startPulling = false |
|
||||
if (state.status === "releasing" && state.distance > state.distThreshold) { |
|
||||
state.status = "refreshing" |
|
||||
state.distance = state.distThreshold |
|
||||
|
|
||||
state.component.addClass("animation") |
|
||||
state.component.setStyle({ |
|
||||
top: setop(state.distance, state.type), |
|
||||
opacity: Math.min(1, state.distance / state.distThreshold), |
|
||||
}) |
|
||||
|
|
||||
ins.triggerEvent("refresh") |
|
||||
} else { |
|
||||
reset(state) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function reset(state) { |
|
||||
state.status = "pending" |
|
||||
state.startPulling = false |
|
||||
state.distance = 0 |
|
||||
state.component.addClass("transition") |
|
||||
state.component.setStyle({ |
|
||||
top: setop(state.distance, state.type), |
|
||||
opacity: 0, |
|
||||
transform: "rotate(0)", |
|
||||
"-webkit-transform": "rotate(0)" |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
function onRefreshed(newValue, oldValue, ins, itemIns) { |
|
||||
if (newValue) { |
|
||||
var state = itemIns.getState() |
|
||||
state.status = "pending" |
|
||||
state.startPulling = false |
|
||||
|
|
||||
var component = state.component || ins.selectComponent(".refresh-wrap") |
|
||||
component.removeClass("animation") |
|
||||
component.addClass("fadeout") |
|
||||
component.setStyle({ |
|
||||
top: (state.distance * 2 - (state.type? 12 : 30)) + "rpx", |
|
||||
opacity: 0, |
|
||||
transform: "scale(0)", |
|
||||
"-webkit-transform": "rotate(0)" |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function setop(distance, type){ |
|
||||
var top = (distance * 2 + (type == 0 ? 120 : -30)) + "rpx" |
|
||||
return top |
|
||||
} |
|
||||
|
|
||||
function onRefreshing(newValue, oldValue, ins, itemIns) { |
|
||||
if (newValue) { |
|
||||
var dataset = itemIns.getDataset() |
|
||||
var state = itemIns.getState() |
|
||||
state.distMax = state.distMax || dataset.distMax |
|
||||
state.distThreshold = state.distThreshold || state.distMax * 0.75 |
|
||||
|
|
||||
state.status = "refreshing" |
|
||||
state.distance = state.distThreshold |
|
||||
state.startPulling = false |
|
||||
state.component = state.component || ins.selectComponent(".refresh-wrap") |
|
||||
|
|
||||
state.component.removeClass("transition") |
|
||||
state.component.removeClass("fadeout") |
|
||||
state.component.addClass("animation") |
|
||||
state.component.setStyle({ |
|
||||
top: setop(state.distance, state.type), |
|
||||
opacity: 1, |
|
||||
transition: "none", |
|
||||
}) |
|
||||
// ins.triggerEvent("refresh") |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
module.exports = { |
|
||||
touchStart: touchStart, |
|
||||
touchMove: touchMove, |
|
||||
touchEnd: touchEnd, |
|
||||
onRefreshed: onRefreshed, |
|
||||
onRefreshing: onRefreshing, |
|
||||
} |
|
||||
/* eslint-enable */ |
|
||||
@ -1,68 +0,0 @@ |
|||||
@keyframes rolling { |
|
||||
0% { |
|
||||
transform: rotate(135deg); |
|
||||
} |
|
||||
100% { |
|
||||
transform: rotate(495deg); |
|
||||
} |
|
||||
} |
|
||||
@keyframes fadeout { |
|
||||
0% { |
|
||||
opacity: 1; |
|
||||
transform: rotate(135deg) scale(1); |
|
||||
} |
|
||||
100% { |
|
||||
opacity: 0; |
|
||||
transform: rotate(135deg) scale(0); |
|
||||
} |
|
||||
} |
|
||||
.refresh-wrap { |
|
||||
position: fixed; |
|
||||
width: 42px; |
|
||||
height: 42px; |
|
||||
left: 50%; |
|
||||
margin-left: -21px; |
|
||||
top: 50px; |
|
||||
z-index: 88; |
|
||||
background-color: #fff; |
|
||||
border-radius: 50%; |
|
||||
box-shadow: 0 0 6px 1px #ccc; |
|
||||
opacity: 0; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
} |
|
||||
.refresh-wrap.transition { |
|
||||
transition: top 0.3s ease-in-out, opacity 0.3s ease-in-out, transform 0.3s ease-in-out; |
|
||||
} |
|
||||
.refresh-wrap.animation { |
|
||||
transition: top 0.3s ease-in-out, opacity 0.3s ease-in-out; |
|
||||
animation: rolling 0.6s linear infinite; |
|
||||
} |
|
||||
.refresh-wrap.fadeout { |
|
||||
animation: fadeout 0.3s ease-in-out; |
|
||||
} |
|
||||
.refresh-wrap .refresh { |
|
||||
box-sizing: border-box; |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
border-radius: 50%; |
|
||||
border: 3px solid #000; |
|
||||
border-top-color: transparent !important; |
|
||||
} |
|
||||
.refresh-wrap.fadeout .refresh { |
|
||||
opacity: 0; |
|
||||
} |
|
||||
.wrap { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
position: relative; |
|
||||
} |
|
||||
.wrap .intersection-dot { |
|
||||
position: absolute; |
|
||||
width: 10px; |
|
||||
height: 10px; |
|
||||
left: 0; |
|
||||
top: 0; |
|
||||
visibility: hidden; |
|
||||
} |
|
||||
@ -0,0 +1,116 @@ |
|||||
|
/** |
||||
|
* 组件:refresher |
||||
|
* 版本:v0.0.1 |
||||
|
* 维护人:Meeken |
||||
|
*/ |
||||
|
const janComponent = require("../_common/jan-component") |
||||
|
const mixinComponent = require("../_common/mixin-component") |
||||
|
const mapScrollView = require("../_common/scroll-view") |
||||
|
|
||||
|
/* 使用 janComponent 初始化组件配置 */ |
||||
|
|
||||
|
let options = janComponent({ |
||||
|
options: { |
||||
|
multipleSlots: true // 在组件定义时的选项中启用多slot支持
|
||||
|
}, |
||||
|
|
||||
|
properties: { |
||||
|
refresherTextStyle: { |
||||
|
type: String, |
||||
|
value: "black" |
||||
|
}, |
||||
|
refresherBackground: { |
||||
|
type: String, |
||||
|
value: "inherit" |
||||
|
}, |
||||
|
triggered: { |
||||
|
type: Boolean, |
||||
|
value: false |
||||
|
}, |
||||
|
threshold: { |
||||
|
type: Number, |
||||
|
value: 50 |
||||
|
}, |
||||
|
restoredText: { |
||||
|
type: String, |
||||
|
value: "下拉刷新" |
||||
|
}, |
||||
|
pullingText: { |
||||
|
type: String, |
||||
|
value: "松开刷新" |
||||
|
}, |
||||
|
refreshingText: { |
||||
|
type: String, |
||||
|
value: "正在刷新" |
||||
|
}, |
||||
|
useSlotStyle: Boolean |
||||
|
}, |
||||
|
|
||||
|
data: { |
||||
|
_state: "下拉刷新", |
||||
|
_stateCode: 0, |
||||
|
_process: 0 |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
options = mixinComponent(options, mapScrollView()) |
||||
|
|
||||
|
options = mixinComponent(options, { |
||||
|
methods: { |
||||
|
on2Upper(e) { |
||||
|
this.$emit("scrolltoupper", e) |
||||
|
}, |
||||
|
|
||||
|
on2Lower(e) { |
||||
|
this.$emit("scrolltolower", e) |
||||
|
}, |
||||
|
|
||||
|
onScroll(e) { |
||||
|
this.$emit("scroll", e) |
||||
|
}, |
||||
|
|
||||
|
onPulling(e) { |
||||
|
const dy = e.detail.dy, |
||||
|
threshold = this.properties.threshold |
||||
|
this.setData({ |
||||
|
_process: dy / threshold, |
||||
|
_stateCode: 1, |
||||
|
_state: dy < threshold ? |
||||
|
this.properties.restoredText : |
||||
|
this.properties.pullingText |
||||
|
}) |
||||
|
this.$emit("pulling", e) |
||||
|
}, |
||||
|
|
||||
|
onRefreshed(e) { |
||||
|
this.setData({ |
||||
|
_state: this.properties.refreshingText, |
||||
|
_stateCode: 2, |
||||
|
_process: 1 |
||||
|
}) |
||||
|
this.$emit("refresh", e) |
||||
|
}, |
||||
|
|
||||
|
onRestored(e) { |
||||
|
this.setData({ |
||||
|
_state: "", |
||||
|
_stateCode: 0, |
||||
|
_process: 0 |
||||
|
}) |
||||
|
this.$emit("restore", e) |
||||
|
}, |
||||
|
|
||||
|
onAbort(e) { |
||||
|
this.setData({ |
||||
|
_state: "", |
||||
|
_stateCode: 0, |
||||
|
_process: 0 |
||||
|
}) |
||||
|
this.$emit("abort", e) |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
attached() {} |
||||
|
}) |
||||
|
|
||||
|
Component(options) |
||||
@ -0,0 +1,5 @@ |
|||||
|
{ |
||||
|
"component": true, |
||||
|
"usingComponents": { |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
<scroll-view class="jan-refresher {{ customClass }}" scroll-y enable-back-to-top refresher-enabled refresher-threshold="{{ threshold }}" refresher-default-style="{{ !useSlotStyle ? refresherTextStyle : 'null' }}" refresher-background="{{ refresherBackground }}" refresher-triggered="{{ triggered }}" bindscrolltoupper="on2Upper" bindscrolltolower="on2Lower" bindscroll="onScroll" bindrefresherpulling="onPulling" bindrefresherrefresh="onRefreshed" bindrefresherrestore="onRestored" bindrefresherabort="onAbort" scroll-x="{{ scrollX }}" scroll-y="{{ scrollY }}" upper-threshold="{{ upperThreshold }}" lower-threshold="{{ lowerThreshold }}" scroll-top="{{ scrollTop }}" scroll-left="{{ scrollLeft }}" scroll-into-view="{{ scrollIntoView }}" scroll-with-animation="{{ scrollWithAnimation }}" enable-back-to-top="{{ enableBackToTop }}" enable-flex="{{ enableFlex }}" scroll-anchoring="{{ scrollAnchoring }}"> |
||||
|
<view wx:if="{{ useSlotStyle }}" slot="refresher" class="jan-refresh--node"> |
||||
|
<view wx:if="{{ _state }}" class="jan-refresher--icon {{ _stateCode === 2 ? 'refreshing' : '' }}" style="font-weight: 600 !important;margin-right: 16rpx;transform: rotate({{ (_process > 1 ? 1 : _process) * 360 }}deg);margin-top:8rpx"> |
||||
|
<text class="cuIcon-refresh text-black"></text> |
||||
|
</view> |
||||
|
<view>{{ _state }}</view> |
||||
|
</view> |
||||
|
<slot></slot> |
||||
|
<view class="jan-refresher--safety-block" /> |
||||
|
</scroll-view> |
||||
@ -0,0 +1,33 @@ |
|||||
|
.jan-refresh--node { |
||||
|
width: 100%; |
||||
|
height: 50px; |
||||
|
background-color: var(--bg-color); |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.jan-refresher--safety-block { |
||||
|
width: 2rpx; |
||||
|
height: 2rpx; |
||||
|
bottom: -2rpx; |
||||
|
position: absolute; |
||||
|
} |
||||
|
|
||||
|
.jan-refresher--icon.refreshing { |
||||
|
transition: all 0.3s; |
||||
|
animation: rotate 0.5s linear infinite; |
||||
|
} |
||||
|
|
||||
|
@keyframes rotate { |
||||
|
0% { |
||||
|
transform: rotate(0); |
||||
|
} |
||||
|
50% { |
||||
|
transform: rotate(180deg); |
||||
|
} |
||||
|
100% { |
||||
|
transform: rotate(360deg); |
||||
|
} |
||||
|
} |
||||
@ -1,7 +1,7 @@ |
|||||
{ |
{ |
||||
"component": true, |
"component": true, |
||||
"usingComponents": { |
"usingComponents": { |
||||
"refresh-view": "/components/refresh-view/index", |
|
||||
|
"refresh-view": "/components/refresher/index", |
||||
"wux-button": "/components/button/index", |
"wux-button": "/components/button/index", |
||||
"wux-tab": "/components/tab/index", |
"wux-tab": "/components/tab/index", |
||||
"wux-divider": "/components/divider/index" |
"wux-divider": "/components/divider/index" |
||||
|
|||||
@ -1,6 +1,6 @@ |
|||||
{ |
{ |
||||
"usingComponents": { |
"usingComponents": { |
||||
"refresh-view": "/components/refresh-view/index", |
|
||||
|
"refresh-view": "/components/refresher/index", |
||||
"wux-button": "/components/button/index", |
"wux-button": "/components/button/index", |
||||
"wux-tab": "/components/tab/index", |
"wux-tab": "/components/tab/index", |
||||
"wux-image": "/components/image/index" |
"wux-image": "/components/image/index" |
||||
|
|||||
@ -1,7 +1,7 @@ |
|||||
{ |
{ |
||||
"component": true, |
"component": true, |
||||
"usingComponents": { |
"usingComponents": { |
||||
"refresh-view": "/components/refresh-view/index", |
|
||||
|
"refresh-view": "/components/refresher/index", |
||||
"wux-button": "/components/button/index" |
"wux-button": "/components/button/index" |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// refresh.js
|
||||
|
Page({ |
||||
|
|
||||
|
/** |
||||
|
* 页面的初始数据 |
||||
|
*/ |
||||
|
data: { |
||||
|
refresherState: false |
||||
|
}, |
||||
|
|
||||
|
onRefresh(e) { |
||||
|
this.setData({ |
||||
|
refresherState: true |
||||
|
}) |
||||
|
setTimeout(() => { |
||||
|
this.setData({ |
||||
|
refresherState: false |
||||
|
}) |
||||
|
}, 3000) |
||||
|
}, |
||||
|
|
||||
|
onLoad() { |
||||
|
setTimeout(() => { |
||||
|
this.setData({ |
||||
|
refresherState: true |
||||
|
}) |
||||
|
}, 3000) |
||||
|
}, |
||||
|
|
||||
|
onPulling(e) { |
||||
|
console.log(e) |
||||
|
} |
||||
|
}) |
||||
@ -0,0 +1,5 @@ |
|||||
|
{ |
||||
|
"usingComponents": { |
||||
|
"refresh-view": "/components/refresher/index" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
<view style="height:150rpx;width:100%"> |
||||
|
</view> |
||||
|
|
||||
|
<refresh-view bind:refresh="onRefresh" triggered="{{ refresherState }}"> |
||||
|
<view class="test-block">师德师风</view> |
||||
|
</refresh-view> |
||||
@ -0,0 +1,10 @@ |
|||||
|
.test-block { |
||||
|
width: 100vw; |
||||
|
height: 500px; |
||||
|
background: pink; |
||||
|
} |
||||
|
/* |
||||
|
.yoo { |
||||
|
width: 100vw; |
||||
|
height: 400px; |
||||
|
} */ |
||||
Write
Preview
Loading…
Cancel
Save