Commit 9d200c0c authored by wlxuqu's avatar wlxuqu

1. 优化懒加载的方法

2. 优化步进器的代码逻辑
3. 修改评分组件对支付宝小程序的支持
4. 添加搜索组件的maxlength参数
5. 优化$u.getRect()方法,使其支持支付宝小程序
parent 95fd1c8e
<template> <template>
<view class="content"> <view class="content">
<view class="cropper-wrapper" :style="{height: cropperOpt.height + 'px'}"> <view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
<canvas class="cropper" :disable-scroll="true" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" <canvas
:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }" canvas-id="cropper"></canvas> class="cropper"
<canvas class="cropper" :disable-scroll="true" :style="{ :disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }"
canvas-id="cropper"
></canvas>
<canvas
class="cropper"
:disable-scroll="true"
:style="{
position: 'fixed', position: 'fixed',
top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`, top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`, left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
width: `${cropperOpt.width * cropperOpt.pixelRatio}px`, width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
height: `${cropperOpt.height * cropperOpt.pixelRatio}` height: `${cropperOpt.height * cropperOpt.pixelRatio}`
}" }"
canvas-id="targetId"> canvas-id="targetId"
</canvas> ></canvas>
</view> </view>
<view class="cropper-buttons safe-area-padding" :style="{height: bottomNavHeight + 'px'}"> <view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
<view class="upload" @tap="uploadTap">重新选择</view> <view class="upload" @tap="uploadTap">重新选择</view>
<view class="getCropperImage" @tap="getCropperImage(false)">确定</view> <view class="getCropperImage" @tap="getCropperImage(false)">确定</view>
</view> </view>
...@@ -21,8 +31,8 @@ ...@@ -21,8 +31,8 @@
</template> </template>
<script> <script>
import WeCropper from './weCropper.js'; import WeCropper from './weCropper.js';
export default { export default {
props: { props: {
// 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色, // 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色,
// mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)" // mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)"
...@@ -33,9 +43,9 @@ ...@@ -33,9 +43,9 @@
lineWidth: 4, lineWidth: 4,
borderColor: 'rgb(245, 245, 245)', borderColor: 'rgb(245, 245, 245)',
mask: 'rgba(0, 0, 0, 0.35)' mask: 'rgba(0, 0, 0, 0.35)'
};
} }
} }
},
// // 裁剪框宽度,单位rpx // // 裁剪框宽度,单位rpx
// rectWidth: { // rectWidth: {
// type: [String, Number], // type: [String, Number],
...@@ -87,13 +97,13 @@ ...@@ -87,13 +97,13 @@
x: (this.width - this.originWidth) / 2, x: (this.width - this.originWidth) / 2,
y: (this.height - this.originWidth) / 2, y: (this.height - this.originWidth) / 2,
width: this.originWidth, width: this.originWidth,
height: this.originWidth, height: this.originWidth
}, },
boundStyle: { boundStyle: {
lineWidth: uni.upx2px(this.boundStyle.lineWidth), lineWidth: uni.upx2px(this.boundStyle.lineWidth),
mask: this.boundStyle.mask, mask: this.boundStyle.mask,
color: this.boundStyle.borderColor color: this.boundStyle.borderColor
}, }
}, },
// 裁剪框和输出图片的尺寸,高度默认等于宽度 // 裁剪框和输出图片的尺寸,高度默认等于宽度
// 输出图片宽度,单位px // 输出图片宽度,单位px
...@@ -101,8 +111,8 @@ ...@@ -101,8 +111,8 @@
// 裁剪框宽度,单位px // 裁剪框宽度,单位px
rectWidth: 200, rectWidth: 200,
// 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可 // 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可
fileType: 'jpg', fileType: 'jpg'
} };
}, },
onLoad(option) { onLoad(option) {
let rectInfo = uni.getSystemInfoSync(); let rectInfo = uni.getSystemInfoSync();
...@@ -112,41 +122,42 @@ ...@@ -112,41 +122,42 @@
this.cropperOpt.height = this.height; this.cropperOpt.height = this.height;
this.cropperOpt.pixelRatio = rectInfo.pixelRatio; this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
if(option.destWidth) this.destWidth = option.destWidth; if (option.destWidth) this.destWidth = option.destWidth;
if(option.rectWidth){ if (option.rectWidth) {
let rectWidth = Number(option.rectWidth); let rectWidth = Number(option.rectWidth);
this.cropperOpt.cut = { this.cropperOpt.cut = {
x: (this.width - rectWidth) / 2, x: (this.width - rectWidth) / 2,
y: (this.height - rectWidth) / 2, y: (this.height - rectWidth) / 2,
width: rectWidth, width: rectWidth,
height: rectWidth, height: rectWidth
};
} }
} this.rectWidth = option.rectWidth; this.rectWidth = option.rectWidth;
if(option.fileType) this.fileType = option.fileType; if (option.fileType) this.fileType = option.fileType;
// 初始化 // 初始化
this.cropper = new WeCropper(this.cropperOpt) this.cropper = new WeCropper(this.cropperOpt)
.on('ready', (ctx) => { .on('ready', ctx => {
// console.log(`wecropper is ready for work!`) // console.log(`wecropper is ready for work!`)
}) })
.on('beforeImageLoad', (ctx) => { .on('beforeImageLoad', ctx => {
// console.log(`before picture loaded, i can do something`) // console.log(`before picture loaded, i can do something`)
}) })
.on('imageLoad', (ctx) => { .on('imageLoad', ctx => {
// console.log(`picture loaded`) // console.log(`picture loaded`)
}) })
.on('beforeDraw', (ctx, instance) => { .on('beforeDraw', (ctx, instance) => {
// console.log(`before canvas draw,i can do something`) // console.log(`before canvas draw,i can do something`)
}) });
// 设置导航栏样式,以免用户在page.json中没有设置为黑色背景 // 设置导航栏样式,以免用户在page.json中没有设置为黑色背景
uni.setNavigationBarColor({ uni.setNavigationBarColor({
frontColor: '#ffffff', frontColor: '#ffffff',
backgroundColor: '#000000', backgroundColor: '#000000'
}) });
uni.chooseImage({ uni.chooseImage({
count: 1, // 默认9 count: 1, // 默认9
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有 sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: (res) => { success: res => {
let src = res.tempFilePaths[0]; let src = res.tempFilePaths[0];
// 获取裁剪图片资源后,给data添加src属性及其值 // 获取裁剪图片资源后,给data添加src属性及其值
this.cropper.pushOrign(src); this.cropper.pushOrign(src);
...@@ -155,79 +166,79 @@ ...@@ -155,79 +166,79 @@
}, },
methods: { methods: {
touchStart(e) { touchStart(e) {
this.cropper.touchStart(e) this.cropper.touchStart(e);
}, },
touchMove(e) { touchMove(e) {
this.cropper.touchMove(e) this.cropper.touchMove(e);
}, },
touchEnd(e) { touchEnd(e) {
this.cropper.touchEnd(e) this.cropper.touchEnd(e);
}, },
getCropperImage(isPre = false) { getCropperImage(isPre = false) {
let cropper_opt = { let cropper_opt = {
destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值 destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值
destWidth: Number(this.destWidth), destWidth: Number(this.destWidth),
fileType: this.fileType, fileType: this.fileType
} };
this.cropper.getCropperImage(cropper_opt, (path, err) => { this.cropper.getCropperImage(cropper_opt, (path, err) => {
if (err) { if (err) {
uni.showModal({ uni.showModal({
title: '温馨提示', title: '温馨提示',
content: err.message content: err.message
}) });
} else { } else {
if(isPre) { if (isPre) {
uni.previewImage({ uni.previewImage({
current: '', // 当前显示图片的 http 链接 current: '', // 当前显示图片的 http 链接
urls: [path] // 需要预览的图片 http 链接列表 urls: [path] // 需要预览的图片 http 链接列表
}) });
} else { } else {
uni.$emit('uAvatarCropper', path); uni.$emit('uAvatarCropper', path);
this.$u.route({ this.$u.route({
type: 'back' type: 'back'
}) });
} }
} }
}) });
}, },
uploadTap() { uploadTap() {
const self = this const self = this;
uni.chooseImage({ uni.chooseImage({
count: 1, // 默认9 count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success(res) { success(res) {
const src = res.tempFilePaths[0] const src = res.tempFilePaths[0];
// 获取裁剪图片资源后,给data添加src属性及其值 // 获取裁剪图片资源后,给data添加src属性及其值
self.cropper.pushOrign(src) self.cropper.pushOrign(src);
} }
}) });
},
} }
} }
};
</script> </script>
<style scoped> <style scoped>
.content { .content {
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
} }
.cropper { .cropper {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 99999999999999; z-index: 99999999999999;
} }
.cropper-buttons { .cropper-buttons {
background-color: #000000; background-color: #000000;
color: #eee; color: #eee;
} }
.cropper-wrapper { .cropper-wrapper {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
...@@ -235,9 +246,9 @@ ...@@ -235,9 +246,9 @@
align-items: center; align-items: center;
width: 100%; width: 100%;
background-color: #000; background-color: #000;
} }
.cropper-buttons { .cropper-buttons {
width: 100vw; width: 100vw;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
...@@ -247,21 +258,21 @@ ...@@ -247,21 +258,21 @@
bottom: 0; bottom: 0;
left: 0; left: 0;
font-size: 28rpx; font-size: 28rpx;
} }
.cropper-buttons .upload, .cropper-buttons .upload,
.cropper-buttons .getCropperImage { .cropper-buttons .getCropperImage {
width: 50%; width: 50%;
text-align: center; text-align: center;
} }
.cropper-buttons .upload { .cropper-buttons .upload {
text-align: left; text-align: left;
padding-left: 50rpx; padding-left: 50rpx;
} }
.cropper-buttons .getCropperImage { .cropper-buttons .getCropperImage {
text-align: right; text-align: right;
padding-right: 50rpx; padding-right: 50rpx;
} }
</style> </style>
<template> <template>
<button id="u-wave-btn" class="u-btn u-line-1 u-fix-ios-appearance" :class="[ <button
id="u-wave-btn"
class="u-btn u-line-1 u-fix-ios-appearance"
:class="[
'u-size-' + size, 'u-size-' + size,
plain ? 'u-' + type + '-plain' : '', plain ? 'u-' + type + '-plain' : '',
loading ? 'u-loading' : '', loading ? 'u-loading' : '',
shape == 'circle' ? 'u-round-circle' : '', shape == 'circle' ? 'u-round-circle' : '',
hairLine ? showHairLineBorder : 'u-bold-border', hairLine ? showHairLineBorder : 'u-bold-border'
]" ]"
:disabled="disabled" :form-type="formType" :open-type="openType" :app-parameter="appParameter" :disabled="disabled"
:hover-stop-propagation="hoverStopPropagation" :send-message-title="sendMessageTitle" send-message-path="sendMessagePath" :form-type="formType"
:lang="lang" :session-from="sessionFrom" :send-message-img="sendMessageImg" :show-message-card="showMessageCard" :open-type="openType"
@getphonenumber="getphonenumber" @getuserinfo="getuserinfo" @error="error" @opensetting="opensetting" @launchapp="launchapp" :app-parameter="appParameter"
:style="[buttonStyle]" @tap="click($event)" :hover-class="getHoverClass" :loading="loading"> :hover-stop-propagation="hoverStopPropagation"
:send-message-title="sendMessageTitle"
send-message-path="sendMessagePath"
:lang="lang"
:session-from="sessionFrom"
:send-message-img="sendMessageImg"
:show-message-card="showMessageCard"
@getphonenumber="getphonenumber"
@getuserinfo="getuserinfo"
@error="error"
@opensetting="opensetting"
@launchapp="launchapp"
:style="[buttonStyle]"
@tap="click($event)"
:hover-class="getHoverClass"
:loading="loading"
>
<slot></slot> <slot></slot>
<view v-if="ripple" class="u-wave-ripple" :class="[waveActive ? 'u-wave-active' : '']" :style="{ <view
'top': rippleTop + 'px', v-if="ripple"
'left': rippleLeft + 'px', class="u-wave-ripple"
'width': fields.targetWidth + 'px', :class="[waveActive ? 'u-wave-active' : '']"
'height': fields.targetWidth + 'px', :style="{
'background-color': (rippleBgColor || 'rgba(0, 0, 0, 0.15)') top: rippleTop + 'px',
}"> left: rippleLeft + 'px',
</view> width: fields.targetWidth + 'px',
height: fields.targetWidth + 'px',
'background-color': rippleBgColor || 'rgba(0, 0, 0, 0.15)'
}"
></view>
</button> </button>
</template> </template>
<script> <script>
/** /**
* button 按钮 * button 按钮
* @description Button 按钮 * @description Button 按钮
* @tutorial https://www.uviewui.com/components/button.html * @tutorial https://www.uviewui.com/components/button.html
...@@ -51,8 +74,8 @@ ...@@ -51,8 +74,8 @@
* @event {Function} launchapp 打开 APP 成功的回调 * @event {Function} launchapp 打开 APP 成功的回调
* @example <u-button>月落</u-button> * @example <u-button>月落</u-button>
*/ */
export default { export default {
name:"u-button", name: 'u-button',
props: { props: {
// 是否细边框 // 是否细边框
hairLine: { hairLine: {
...@@ -169,8 +192,8 @@ ...@@ -169,8 +192,8 @@
// 自定义样式,对象形式 // 自定义样式,对象形式
customStyle: { customStyle: {
type: Object, type: Object,
default () { default() {
return {} return {};
} }
} }
}, },
...@@ -188,13 +211,13 @@ ...@@ -188,13 +211,13 @@
let style = {}; let style = {};
if (this.type == 'default') { if (this.type == 'default') {
if (this.disabled) { if (this.disabled) {
style.color = "#c0c4cc"; style.color = '#c0c4cc';
style.backgroundColor = "#ffffff"; style.backgroundColor = '#ffffff';
style.borderColor = "#e4e7ed"; style.borderColor = '#e4e7ed';
} else { } else {
style.color = this.$u.color['contentColor']; style.color = this.$u.color['contentColor'];
style.backgroundColor = "#ffffff"; style.backgroundColor = '#ffffff';
style.borderColor = "#c0c4cc"; style.borderColor = '#c0c4cc';
} }
} else { } else {
if (this.disabled) { if (this.disabled) {
...@@ -203,17 +226,17 @@ ...@@ -203,17 +226,17 @@
style.backgroundColor = this.$u.color[this.type + 'Light']; style.backgroundColor = this.$u.color[this.type + 'Light'];
style.borderColor = this.$u.color[this.type + 'Disabled']; style.borderColor = this.$u.color[this.type + 'Disabled'];
} else { } else {
style.color = "#ffffff"; style.color = '#ffffff';
style.backgroundColor = this.$u.color[this.type + 'Disabled']; style.backgroundColor = this.$u.color[this.type + 'Disabled'];
style.borderColor = this.$u.color[this.type + 'Disabled']; style.borderColor = this.$u.color[this.type + 'Disabled'];
} }
} else { } else {
if (this.plain) { if (this.plain) {
style.color = this.$u.color[this.type] style.color = this.$u.color[this.type];
style.backgroundColor = this.$u.color[this.type + 'Light']; style.backgroundColor = this.$u.color[this.type + 'Light'];
style.borderColor = this.$u.color[this.type + 'Disabled']; style.borderColor = this.$u.color[this.type + 'Disabled'];
} else { } else {
style.color = "#ffffff"; style.color = '#ffffff';
style.backgroundColor = this.$u.color[this.type]; style.backgroundColor = this.$u.color[this.type];
style.borderColor = this.$u.color[this.type]; style.borderColor = this.$u.color[this.type];
} }
...@@ -236,8 +259,8 @@ ...@@ -236,8 +259,8 @@
rippleTop: 0, // 水波纹的起点Y坐标到按钮上边界的距离 rippleTop: 0, // 水波纹的起点Y坐标到按钮上边界的距离
rippleLeft: 0, // 水波纹起点X坐标到按钮左边界的距离 rippleLeft: 0, // 水波纹起点X坐标到按钮左边界的距离
fields: {}, // 波纹按钮节点信息 fields: {}, // 波纹按钮节点信息
waveActive: false, // 激活水波纹 waveActive: false // 激活水波纹
} };
}, },
methods: { methods: {
// 按钮点击 // 按钮点击
...@@ -263,7 +286,7 @@ ...@@ -263,7 +286,7 @@
if (!data.width || !data.width) return; if (!data.width || !data.width) return;
// 水波纹的最终形态是一个正方形(通过border-radius让其变为一个圆形),这里要保证正方形的边长等于按钮的最长边 // 水波纹的最终形态是一个正方形(通过border-radius让其变为一个圆形),这里要保证正方形的边长等于按钮的最长边
// 最终的方形(变换后的圆形)才能覆盖整个按钮 // 最终的方形(变换后的圆形)才能覆盖整个按钮
data.targetWidth = (data.height > data.width ? data.height : data.width); data.targetWidth = data.height > data.width ? data.height : data.width;
if (!data.targetWidth) return; if (!data.targetWidth) return;
this.fields = data; this.fields = data;
let touchesX = '', let touchesX = '',
...@@ -283,12 +306,12 @@ ...@@ -283,12 +306,12 @@
// 获取触摸点相对于按钮上边和左边的x和y坐标,原理是通过屏幕的触摸点(touchesY),减去按钮的上边界data.top // 获取触摸点相对于按钮上边和左边的x和y坐标,原理是通过屏幕的触摸点(touchesY),减去按钮的上边界data.top
// 但是由于`transform-origin`默认是center,所以这里再减去半径才是水波纹view应该的位置 // 但是由于`transform-origin`默认是center,所以这里再减去半径才是水波纹view应该的位置
// 总的来说,就是把水波纹的矩形(变换后的圆形)的中心点,移动到我们的触摸点位置 // 总的来说,就是把水波纹的矩形(变换后的圆形)的中心点,移动到我们的触摸点位置
this.rippleTop = (touchesY - data.top - (data.targetWidth / 2)); this.rippleTop = touchesY - data.top - data.targetWidth / 2;
this.rippleLeft = (touchesX - data.left - (data.targetWidth / 2)); this.rippleLeft = touchesX - data.left - data.targetWidth / 2;
this.$nextTick(() => { this.$nextTick(() => {
this.waveActive = true; this.waveActive = true;
}) });
}) });
}, },
// 获取节点信息 // 获取节点信息
getElQuery() { getElQuery() {
...@@ -301,10 +324,10 @@ ...@@ -301,10 +324,10 @@
queryInfo = uni.createSelectorQuery(); queryInfo = uni.createSelectorQuery();
//#endif //#endif
queryInfo.select('.u-btn').boundingClientRect(); queryInfo.select('.u-btn').boundingClientRect();
queryInfo.exec((data) => { queryInfo.exec(data => {
resolve(data) resolve(data);
});
}); });
})
}, },
// 下面为对接uniapp官方按钮开放能力事件回调的对接 // 下面为对接uniapp官方按钮开放能力事件回调的对接
getphonenumber(res) { getphonenumber(res) {
...@@ -321,17 +344,17 @@ ...@@ -321,17 +344,17 @@
}, },
launchapp(res) { launchapp(res) {
this.$emit('launchapp', res); this.$emit('launchapp', res);
},
} }
} }
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.u-btn::after { .u-btn::after {
border: none; border: none;
} }
.u-btn { .u-btn {
position: relative; position: relative;
border: 0; border: 0;
//border-radius: 10rpx; //border-radius: 10rpx;
...@@ -346,9 +369,9 @@ ...@@ -346,9 +369,9 @@
z-index: 1; z-index: 1;
box-sizing: border-box; box-sizing: border-box;
transition: all 0.15s; transition: all 0.15s;
} }
.u-hairline-border:after { .u-hairline-border:after {
content: ' '; content: ' ';
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
...@@ -365,13 +388,13 @@ ...@@ -365,13 +388,13 @@
transform: scale(0.5, 0.5); transform: scale(0.5, 0.5);
border: 1px solid currentColor; border: 1px solid currentColor;
z-index: 0; z-index: 0;
} }
.u-bold-border { .u-bold-border {
border: 1px solid #FFFFFF; border: 1px solid #ffffff;
} }
.u-wave-ripple { .u-wave-ripple {
z-index: 0; z-index: 0;
position: absolute; position: absolute;
border-radius: 100%; border-radius: 100%;
...@@ -381,42 +404,42 @@ ...@@ -381,42 +404,42 @@
transform: scale(0); transform: scale(0);
opacity: 1; opacity: 1;
transform-origin: center; transform-origin: center;
} }
.u-wave-ripple.u-wave-active { .u-wave-ripple.u-wave-active {
opacity: 0; opacity: 0;
transform: scale(2); transform: scale(2);
transition: opacity 1s linear, transform 0.4s linear; transition: opacity 1s linear, transform 0.4s linear;
} }
.u-round-circle { .u-round-circle {
border-radius: 100rpx; border-radius: 100rpx;
} }
.u-round-circle::after { .u-round-circle::after {
border-radius: 100rpx; border-radius: 100rpx;
} }
.u-loading::after { .u-loading::after {
background-color: hsla(0, 0%, 100%, .35); background-color: hsla(0, 0%, 100%, 0.35);
} }
.u-size-default { .u-size-default {
font-size: 30rpx; font-size: 30rpx;
height: 80rpx; height: 80rpx;
line-height: 80rpx; line-height: 80rpx;
} }
.u-size-medium { .u-size-medium {
display: inline-flex; display: inline-flex;
width: auto; width: auto;
font-size: 26rpx; font-size: 26rpx;
height: 70rpx; height: 70rpx;
line-height: 70rpx; line-height: 70rpx;
padding: 0 80rpx; padding: 0 80rpx;
} }
.u-size-mini { .u-size-mini {
display: inline-flex; display: inline-flex;
width: auto; width: auto;
font-size: 22rpx; font-size: 22rpx;
...@@ -424,67 +447,66 @@ ...@@ -424,67 +447,66 @@
height: 50rpx; height: 50rpx;
line-height: 50rpx; line-height: 50rpx;
padding: 0 20rpx; padding: 0 20rpx;
} }
.u-primary-plain-hover { .u-primary-plain-hover {
color: #FFFFFF !important; color: #ffffff !important;
background: $u-type-primary-dark !important; background: $u-type-primary-dark !important;
} }
.u-default-plain-hover { .u-default-plain-hover {
color: $u-type-primary-dark !important; color: $u-type-primary-dark !important;
background: $u-type-primary-light !important; background: $u-type-primary-light !important;
} }
.u-success-plain-hover { .u-success-plain-hover {
color: #FFFFFF !important; color: #ffffff !important;
background: $u-type-success-dark !important; background: $u-type-success-dark !important;
} }
.u-warning-plain-hover { .u-warning-plain-hover {
color: #FFFFFF !important; color: #ffffff !important;
background: $u-type-warning-dark !important; background: $u-type-warning-dark !important;
} }
.u-error-plain-hover { .u-error-plain-hover {
color: #FFFFFF !important; color: #ffffff !important;
background: $u-type-error-dark !important; background: $u-type-error-dark !important;
} }
.u-info-plain-hover { .u-info-plain-hover {
color: #FFFFFF !important; color: #ffffff !important;
background: $u-type-info-dark !important; background: $u-type-info-dark !important;
} }
.u-default-hover { .u-default-hover {
color: $u-type-primary-dark !important; color: $u-type-primary-dark !important;
border-color: $u-type-primary-dark !important; border-color: $u-type-primary-dark !important;
background-color: $u-type-primary-light !important; background-color: $u-type-primary-light !important;
; }
}
.u-primary-hover { .u-primary-hover {
background: $u-type-primary-dark !important; background: $u-type-primary-dark !important;
color: #fff; color: #fff;
} }
.u-success-hover { .u-success-hover {
background: $u-type-success-dark !important; background: $u-type-success-dark !important;
color: #fff; color: #fff;
} }
.u-info-hover { .u-info-hover {
background: $u-type-info-dark !important; background: $u-type-info-dark !important;
color: #fff; color: #fff;
} }
.u-warning-hover { .u-warning-hover {
background: $u-type-warning-dark !important; background: $u-type-warning-dark !important;
color: #fff; color: #fff;
} }
.u-error-hover { .u-error-hover {
background: $u-type-error-dark !important; background: $u-type-error-dark !important;
color: #fff; color: #fff;
} }
</style> </style>
...@@ -76,17 +76,17 @@ export default { ...@@ -76,17 +76,17 @@ export default {
}, },
// 左侧标题 // 左侧标题
title: { title: {
type: String, type: [String, Number],
default: '' default: ''
}, },
// 右侧内容 // 右侧内容
value: { value: {
type: String, type: [String, Number],
default: '' default: ''
}, },
// 标题下方的描述信息 // 标题下方的描述信息
label: { label: {
type: String, type: [String, Number],
default: '' default: ''
}, },
// 是否显示内边框 // 是否显示内边框
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
</template> </template>
<script> <script>
// observer最终赋值的是个对象,不能放到data中,vue会报错(浏览器),也不能在用到的地方let定义,某些安卓也报错……
let observer = {};
/** /**
* lazyLoad 懒加载 * lazyLoad 懒加载
* @description 懒加载使用的场景为:页面有很多图片时,APP会同时加载所有的图片,导致页面卡顿,各个位置的图片出现前后不一致等. * @description 懒加载使用的场景为:页面有很多图片时,APP会同时加载所有的图片,导致页面卡顿,各个位置的图片出现前后不一致等.
...@@ -116,9 +114,13 @@ ...@@ -116,9 +114,13 @@
}, },
// 计算图片的高度,可能为auto,带%,或者直接数值 // 计算图片的高度,可能为auto,带%,或者直接数值
imgHeight() { imgHeight() {
return this.height == 'auto' ? 'auto' : this.height.indexOf('%') != -1 ? this.height : this.height + 'rpx'; return this.height == 'auto' ? 'auto' : String(this.height).indexOf('%') != -1 ? this.height : this.height + 'rpx';
} }
}, },
created() {
// 由于一些特殊原因,不能将此变量放到data中定义
this.observer = {};
},
watch: { watch: {
isShow(nVal) { isShow(nVal) {
// 如果是不开启过渡效果,直接返回 // 如果是不开启过渡效果,直接返回
...@@ -166,7 +168,11 @@ ...@@ -166,7 +168,11 @@
// 图片加载失败 // 图片加载失败
loadError() { loadError() {
this.isError = true; this.isError = true;
} },
disconnectObserver(observerName) {
const observer = this[observerName];
observer && observer.disconnect();
},
}, },
beforeDestroy() { beforeDestroy() {
// 销毁页面时,可能还没触发某张很底部的懒加载图片,所以把这个事件给去掉 // 销毁页面时,可能还没触发某张很底部的懒加载图片,所以把这个事件给去掉
...@@ -180,25 +186,23 @@ ...@@ -180,25 +186,23 @@
}); });
}) })
// mounted的时候,不一定挂载了这个元素,延时30ms,否则会报错或者不报错,但是也没有效果 // mounted的时候,不一定挂载了这个元素,延时30ms,否则会报错或者不报错,但是也没有效果
let that = this;
//let observer = null;
setTimeout(() => { setTimeout(() => {
// 这里是组件内获取布局状态,不能用uni.createIntersectionObserver,而必须用this.createIntersectionObserver // 这里是组件内获取布局状态,不能用uni.createIntersectionObserver,而必须用this.createIntersectionObserver
// 因为这样可以把选择器的选取范围定义在自定义组件内 this.disconnectObserver('contentObserver');
// 否则某些安卓机型报错,也不能加this(如createIntersectionObserver(this)),否则某些机型也报错 const contentObserver = uni.createIntersectionObserver(this);
observer = uni.createIntersectionObserver(this);
// 要理解这里怎么计算的,请看这个: // 要理解这里怎么计算的,请看这个:
// https://blog.csdn.net/qq_25324335/article/details/83687695 // https://blog.csdn.net/qq_25324335/article/details/83687695
observer.relativeToViewport({ contentObserver.relativeToViewport({
bottom: that.getThreshold, bottom: this.getThreshold,
}).observe('.u-lazy-item-' + that.elIndex, (res) => { }).observe('.u-lazy-item-' + this.elIndex, (res) => {
if (res.intersectionRatio > 0) { if (res.intersectionRatio > 0) {
// 懒加载状态改变 // 懒加载状态改变
that.isShow = true; this.isShow = true;
// 如果图片已经加载,去掉监听,减少性能的消耗 // 如果图片已经加载,去掉监听,减少性能的消耗
observer.disconnect(); this.disconnectObserver('contentObserver');
} }
}) })
this.contentObserver = contentObserver;
}, 30) }, 30)
} }
} }
......
...@@ -114,8 +114,8 @@ ...@@ -114,8 +114,8 @@
// 为了让用户能够删除所有输入值,重新输入内容,删除所有值后,内容为空字符串 // 为了让用户能够删除所有输入值,重新输入内容,删除所有值后,内容为空字符串
if (v1 == '') return; if (v1 == '') return;
let value = 0; let value = 0;
// 首先判断是否正整数,并且在min和max之间,如果不是,使用原来值 // 首先判断是否正整数,并且第一位数字不为0,并且在min和max之间,如果不是,使用原来值
let tmp = /(^\d+$)/.test(v1) && value[0] != 0; let tmp = /(^\d+$)/.test(v1) && String(v1)[0] != 0;
if (tmp && v1 >= this.min && v1 <= this.max) value = v1; if (tmp && v1 >= this.min && v1 <= this.max) value = v1;
else value = v2; else value = v2;
this.handleChange(value, 'change'); this.handleChange(value, 'change');
......
<template> <template>
<view class="u-rate" :id="elId" @touchmove.stop.prevent="touchMove"> <view class="u-rate" :id="elId" @touchmove.stop.prevent="touchMove">
<view class="u-star-wrap" v-for="(item, index) in count" :key="index" :class="[elClass]"> <view class="u-star-wrap" v-for="(item, index) in count" :key="index" :class="[elClass]">
<u-icon :name="activeIndex > index ? activeIcon : inactiveIcon" @click="click(index + 1, $event)" :style="{ <u-icon
color: activeIndex > index ? activeColor : inactiveColor, :name="activeIndex > index ? activeIcon : inactiveIcon"
@click="click(index + 1, $event)"
:color="activeIndex > index ? activeColor : inactiveColor"
:style="{
fontSize: size + 'rpx', fontSize: size + 'rpx',
padding: `0 ${gutter / 2 + 'rpx'}` padding: `0 ${gutter / 2 + 'rpx'}`
}"></u-icon> }"
></u-icon>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
/** /**
* rate 评分 * rate 评分
* @description 该组件一般用于满意度调查,星型评分的场景 * @description 该组件一般用于满意度调查,星型评分的场景
* @tutorial https://www.uviewui.com/components/rate.html * @tutorial https://www.uviewui.com/components/rate.html
...@@ -27,8 +31,8 @@ ...@@ -27,8 +31,8 @@
* @event {Function} change 选中的星星发生变化时触发 * @event {Function} change 选中的星星发生变化时触发
* @example <u-rate :count="count" :current="2"></u-rate> * @example <u-rate :count="count" :current="2"></u-rate>
*/ */
export default { export default {
name: "u-rate", name: 'u-rate',
props: { props: {
// 要显示的星星数量 // 要显示的星星数量
count: { count: {
...@@ -53,12 +57,12 @@ ...@@ -53,12 +57,12 @@
// 未选中时的颜色 // 未选中时的颜色
inactiveColor: { inactiveColor: {
type: String, type: String,
default: "#b2b2b2" default: '#b2b2b2'
}, },
// 选中的颜色 // 选中的颜色
activeColor: { activeColor: {
type: String, type: String,
default: "#FA3534" default: '#FA3534'
}, },
// 星星之间的间距,单位rpx // 星星之间的间距,单位rpx
gutter: { gutter: {
...@@ -84,7 +88,7 @@ ...@@ -84,7 +88,7 @@
inactiveIcon: { inactiveIcon: {
type: String, type: String,
default: 'star' default: 'star'
}, }
}, },
data() { data() {
return { return {
...@@ -94,8 +98,8 @@ ...@@ -94,8 +98,8 @@
starBoxLeft: 0, // 评分盒子左边到屏幕左边的距离,用于滑动选择时计算距离 starBoxLeft: 0, // 评分盒子左边到屏幕左边的距离,用于滑动选择时计算距离
activeIndex: this.current, // 当前激活的星星的index activeIndex: this.current, // 当前激活的星星的index
starWidth: 0, // 每个星星的宽度 starWidth: 0, // 每个星星的宽度
starWidthArr: [], //每个星星最右边到组件盒子最左边的距离 starWidthArr: [] //每个星星最右边到组件盒子最左边的距离
} };
}, },
watch: { watch: {
current(val) { current(val) {
...@@ -105,30 +109,21 @@ ...@@ -105,30 +109,21 @@
methods: { methods: {
// 获取评分组件盒子的布局信息 // 获取评分组件盒子的布局信息
getElRectById() { getElRectById() {
let query = uni.createSelectorQuery().in(this) // uView封装的获取节点的方法,详见文档
query.select("#" + this.elId).boundingClientRect((res) => { this.$u.getRect('#' + this.elId).then(res => {
// 如果获取不到,延时到本轮代码的末期再尝试
if (!res.left) {
setTimeout(this.getElRectByClass);
return;
}
this.starBoxLeft = res.left; this.starBoxLeft = res.left;
}).exec() })
}, },
// 获取单个星星的尺寸 // 获取单个星星的尺寸
getElRectByClass() { getElRectByClass() {
let query = uni.createSelectorQuery().in(this) // uView封装的获取节点的方法,详见文档
query.select("." + this.elClass).boundingClientRect((res) => { this.$u.getRect('.' + this.elClass).then(res => {
if (!res.width) {
setTimeout(this.getElRectByClass);
return;
}
this.starWidth = res.width; this.starWidth = res.width;
// 把每个星星右边到组件盒子左边的距离放入数组中 // 把每个星星右边到组件盒子左边的距离放入数组中
for (let i = 0; i < this.count; i++) { for (let i = 0; i < this.count; i++) {
this.starWidthArr[i] = (i + 1) * this.starWidth; this.starWidthArr[i] = (i + 1) * this.starWidth;
} }
}).exec() })
}, },
// 手指滑动 // 手指滑动
touchMove(e) { touchMove(e) {
...@@ -151,7 +146,7 @@ ...@@ -151,7 +146,7 @@
this.activeIndex = index > this.count ? this.count : index; this.activeIndex = index > this.count ? this.count : index;
// 对最少颗星星的限制 // 对最少颗星星的限制
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount; if (this.activeIndex < this.minCount) this.activeIndex = this.minCount;
this.$emit('change', this.activeIndex) this.$emit('change', this.activeIndex);
}, },
// 通过点击,直接选中 // 通过点击,直接选中
click(index, e) { click(index, e) {
...@@ -160,7 +155,6 @@ ...@@ -160,7 +155,6 @@
} }
// 半星选择,尚未实现 // 半星选择,尚未实现
if (this.allowHalf) { if (this.allowHalf) {
} }
// 对第一个星星特殊处理,只有一个的时候,点击可以取消,否则无法作0星评价 // 对第一个星星特殊处理,只有一个的时候,点击可以取消,否则无法作0星评价
if (index == 1) { if (index == 1) {
...@@ -171,26 +165,26 @@ ...@@ -171,26 +165,26 @@
} }
// 对最少颗星星的限制 // 对最少颗星星的限制
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount; if (this.activeIndex < this.minCount) this.activeIndex = this.minCount;
this.$emit('change', this.activeIndex) this.$emit('change', this.activeIndex);
}, }
}, },
mounted() { mounted() {
this.getElRectById(); this.getElRectById();
this.getElRectByClass(); this.getElRectByClass();
},
} }
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.u-rate { .u-rate {
display: -webkit-inline-flex; display: -webkit-inline-flex;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.u-icon { .u-icon {
box-sizing: border-box; box-sizing: border-box;
} }
</style> </style>
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
@input="inputChange" @input="inputChange"
:disabled="disabled" :disabled="disabled"
@focus="getFocus" @focus="getFocus"
:maxlength="getMaxlength"
:focus="focus" :focus="focus"
placeholder-class="u-placeholder-class" placeholder-class="u-placeholder-class"
:placeholder="placeholder" :placeholder="placeholder"
...@@ -144,6 +145,11 @@ export default { ...@@ -144,6 +145,11 @@ export default {
default() { default() {
return {} return {}
} }
},
// 输入框最大能输入的长度,-1为不限制长度(来自uniapp文档)
maxlength: {
type: [Number, String],
default: -1
} }
}, },
data() { data() {
...@@ -180,6 +186,10 @@ export default { ...@@ -180,6 +186,10 @@ export default {
borderStyle() { borderStyle() {
if (this.borderColor) return `1px solid ${this.borderColor}`; if (this.borderColor) return `1px solid ${this.borderColor}`;
else return 'none'; else return 'none';
},
// 将maxlength转为数值
getMaxlength() {
return Number(this.maxlength);
} }
}, },
methods: { methods: {
......
This diff is collapsed.
...@@ -10,8 +10,15 @@ module.exports = { ...@@ -10,8 +10,15 @@ module.exports = {
// 查询节点信息 // 查询节点信息
$uGetRect(selector, all) { $uGetRect(selector, all) {
return new Promise(resolve => { return new Promise(resolve => {
uni.createSelectorQuery() let query = null;
.in(this)[all ? 'selectAll' : 'select'](selector) // 支付宝小程序不能加后面的.in(this),是它自身的限制
// #ifndef MP-ALIPAY
query = uni.createSelectorQuery().in(this)
// #endif
// #ifdef MP-ALIPAY
query = uni.createSelectorQuery()
// #endif
query[all ? 'selectAll' : 'select'](selector)
.boundingClientRect(rect => { .boundingClientRect(rect => {
if (all && Array.isArray(rect) && rect.length) { if (all && Array.isArray(rect) && rect.length) {
resolve(rect) resolve(rect)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment