更新slider组件

parent fc236931
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
"easycom": { "easycom": {
"^u-(.*)": "@/uview/components/u-$1/u-$1.vue" "^u-(.*)": "@/uview/components/u-$1/u-$1.vue"
}, },
// "condition": { //模式配置,仅开发期间生效 "condition": { //模式配置,仅开发期间生效
// "current": 0, //当前激活的模式(list 的索引项) "current": 0, //当前激活的模式(list 的索引项)
// "list": [{ "list": [{
// "name": "test", //模式名称 "name": "test", //模式名称
// "path": "pages/componentsA/fullScreen/index", //启动页面,必选 "path": "pages/componentsA/slider/index", //启动页面,必选
// "query": "id=1&name=2" //启动参数,在页面的-+onLoad函数里面得到 "query": "id=1&name=2" //启动参数,在页面的-+onLoad函数里面得到
// }] }]
// }, },
"pages": [ "pages": [
// 演示-组件 // 演示-组件
{ {
...@@ -443,6 +443,13 @@ ...@@ -443,6 +443,13 @@
{ {
"root": "pages/componentsA", "root": "pages/componentsA",
"pages": [ "pages": [
// slider-滑动选择器
{
"path": "slider/index",
"style": {
"navigationBarTitleText": "slider-滑动选择器"
}
},
// fullScreen-压窗屏 // fullScreen-压窗屏
{ {
"path": "fullScreen/index", "path": "fullScreen/index",
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<view class="u-demo-area"> <view class="u-demo-area">
<u-toast ref="uToast"></u-toast> <u-toast ref="uToast"></u-toast>
<view class="u-no-demo-here">请点击弹出弹窗查看效果</view> <view class="u-no-demo-here">请点击弹出弹窗查看效果</view>
<u-modal v-model="show" :show-cancel-button="true" :show-title="showTitle"> <u-modal v-model="show" :show-cancel-button="true" :show-title="showTitle" :content-slot="contentSlot">
<view class="warp" style="margin: 30rpx;" v-if="content"> <view class="warp" style="margin: 30rpx;" v-if="content">
<image class="logo" src="https://uviewui.com/common/logo.png" style="width: 220rpx;" mode="widthFix"></image> <image class="logo" src="https://uviewui.com/common/logo.png" style="width: 220rpx;" mode="widthFix"></image>
</view> </view>
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
show: false, show: false,
zoom: false, zoom: false,
content: false, content: false,
showTitle: true showTitle: true,
contentSlot: false
}; };
}, },
computed: { computed: {
...@@ -48,14 +49,15 @@ ...@@ -48,14 +49,15 @@
}, },
methods: { methods: {
showChange(index) { showChange(index) {
this.show = index == 0 ? true : false; this.show = !index;
}, },
titleChange(index) { titleChange(index) {
this.showTitle = index == 0 ? true : false; this.showTitle = !index;
this.show = true; this.show = true;
}, },
contentChange(index) { contentChange(index) {
this.content = index == 0 ? true : false; this.contentSlot = !index;
this.content = !index;
this.show = true; this.show = true;
} }
} }
......
<template>
<view class="u-demo">
<view class="u-demo-wrap">
<view class="u-demo-title">演示效果</view>
<view class="u-demo-area">
<u-toast ref="uToast"></u-toast>
<u-slider :step="step" :height="height" :block-width="blockWidth"
:active-color="activeColor" :value="30"
:use-slot="useSlot" v-model="value"
:min="min" :max="max"
>
<view class="">
<view class="badge-button" v-if="useSlot">
{{value}}
</view>
</view>
</u-slider>
<view class="u-demo-result-line">
滑块值:{{value}}
</view>
</view>
</view>
<view class="u-config-wrap">
<view class="u-config-title u-border-bottom">参数配置</view>
<view class="u-config-item">
<view class="u-item-title">自定义颜色</view>
<u-subsection vibrateShort :list="['primary', 'warning', 'error', 'success']" @change="typeChange"></u-subsection>
</view>
<view class="u-config-item">
<view class="u-item-title">自定义传入内容</view>
<u-subsection vibrateShort current="1" :list="['是', '否']" @change="slotChange"></u-subsection>
</view>
<view class="u-config-item">
<view class="u-item-title">自定义尺寸</view>
<u-subsection vibrateShort current="1" :list="['是', '否']" @change="sizeChange"></u-subsection>
</view>
<view class="u-config-item">
<view class="u-item-title">步进值</view>
<u-subsection vibrateShort :list="['1', '10', '25']" @change="stepChange"></u-subsection>
</view>
<view class="u-config-item">
<view class="u-item-title">最大最小值</view>
<u-subsection vibrateShort :list="['0-100', '30-80']" @change="minMaxchange"></u-subsection>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
value: 30,
useSlot: false,
setp: 1,
activeColor: '#2979ff',
height: 6,
blockWidth: 30,
step: 1,
min: 0,
max: 100
};
},
onLoad() {
},
computed: {
current() {
return this.show ? 0 : 1;
}
},
methods: {
typeChange(index) {
let type = ['primary', 'warning', 'error', 'success'];
this.activeColor = this.$u.color[type[index]];
},
sizeChange(index) {
if(index == 0) {
this.height = 4;
this.blockWidth = 30;
} else {
this.height = 6;
this.blockWidth = 20;
}
},
stepChange(index) {
let arr = ['1', '10', '30'];
this.step = arr[index];
},
slotChange(index) {
this.useSlot = !index;
},
minMaxchange(index) {
if(index == 0) {
this.min = 0;
this.max = 100;
} else {
this.min = 30;
this.max = 80;
}
}
}
};
</script>
<style scoped lang="scss">
.badge-button {
padding: 4rpx 6rpx;
background-color: $u-type-error;
color: #fff;
border-radius: 10rpx;
font-size: 22rpx;
line-height: 1;
}
</style>
...@@ -76,6 +76,10 @@ export default [{ ...@@ -76,6 +76,10 @@ export default [{
path: '/pages/componentsB/switch/index', path: '/pages/componentsB/switch/index',
icon: 'switch', icon: 'switch',
title: 'Switch 开关选择器', title: 'Switch 开关选择器',
}, {
path: '/pages/componentsA/slider/index',
icon: 'slider',
title: 'Slider 滑动选择器',
}] }]
}, { }, {
groupName: '数据组件', groupName: '数据组件',
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
marginTop: marginTop + 'rpx' marginTop: marginTop + 'rpx'
}" @tap="click"> }" @tap="click">
<view class="u-divider-line" :style="[lineStyle]"></view> <view class="u-divider-line" :style="[lineStyle]"></view>
<view class="u-divider-text" :style="{ <view v-if="useSlot" class="u-divider-text" :style="{
color: color, color: color,
fontSize: fontSize + 'rpx' fontSize: fontSize + 'rpx'
}"><slot /></view> }"><slot /></view>
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
* @property {String} bg-color 整个divider的背景颜色(默认呢#ffffff) * @property {String} bg-color 整个divider的背景颜色(默认呢#ffffff)
* @property {String Number} height 整个divider的高度,单位rpx(默认40) * @property {String Number} height 整个divider的高度,单位rpx(默认40)
* @property {String} type 将线条设置主题色(默认primary) * @property {String} type 将线条设置主题色(默认primary)
* @property {Boolean} useSlot 是否使用slot传入内容,如果不传入,中间不会有空隙(默认true)
* @property {String Number} margin-top 与前一个组件的距离,单位rpx(默认0) * @property {String Number} margin-top 与前一个组件的距离,单位rpx(默认0)
* @property {String Number} margin-bottom 与后一个组件的距离,单位rpx(0) * @property {String Number} margin-bottom 与后一个组件的距离,单位rpx(0)
* @event {Function} click divider组件被点击时触发 * @event {Function} click divider组件被点击时触发
...@@ -79,6 +80,11 @@ export default { ...@@ -79,6 +80,11 @@ export default {
type: [String, Number], type: [String, Number],
default: 0 default: 0
}, },
// 是否使用slot传入内容,如果不用slot传入内容,先的中间就不会有空隙
useSlot: {
type: Boolean,
default: true
}
}, },
computed: { computed: {
lineStyle() { lineStyle() {
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
<view class="u-model"> <view class="u-model">
<view v-if="showTitle" class="u-model-title u-line-1" :style="[titleStyle]">{{ title }}</view> <view v-if="showTitle" class="u-model-title u-line-1" :style="[titleStyle]">{{ title }}</view>
<view class="u-model-content"> <view class="u-model-content">
<slot> <slot v-if="contentSlot">
<view class="u-model-content-meeeage" :style="[contentStyle]">{{ content }}</view>
</slot> </slot>
<view v-else class="u-model-content-meeeage" :style="[contentStyle]">{{ content }}</view>
</view> </view>
<view class="u-model-footer u-border-top"> <view class="u-model-footer u-border-top">
<view <view
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
* @property {Object} cancel-style 自定义取消按钮样式,对象形式 * @property {Object} cancel-style 自定义取消按钮样式,对象形式
* @property {Object} confirm-style 自定义确认按钮样式,对象形式 * @property {Object} confirm-style 自定义确认按钮样式,对象形式
* @property {Boolean} zoom 是否开启缩放模式(默认true) * @property {Boolean} zoom 是否开启缩放模式(默认true)
* @property {Boolean} contentSlot 是否传入自定义的slot内容(默认false)
* @event {Function} confirm 确认按钮被点击 * @event {Function} confirm 确认按钮被点击
* @event {Function} cancel 取消按钮被点击 * @event {Function} cancel 取消按钮被点击
* @example <u-modal :src="title" :content="content"></u-modal> * @example <u-modal :src="title" :content="content"></u-modal>
...@@ -163,7 +164,13 @@ export default { ...@@ -163,7 +164,13 @@ export default {
zoom: { zoom: {
type: Boolean, type: Boolean,
default: true default: true
},
// 是否传入自定义的slot内容,因为微信小程序无法在<slot></slot>中插入内
contentSlot: {
type: Boolean,
default: false
} }
}, },
computed: { computed: {
cancelBtnStyle() { cancelBtnStyle() {
......
...@@ -23,15 +23,18 @@ ...@@ -23,15 +23,18 @@
:placeholder="placeholder" :placeholder="placeholder"
class="u-input" class="u-input"
type="text" type="text"
:style="{ :style="[{
textAlign: inputAlign textAlign: inputAlign
}" }, inputStyle]"
/> />
<view class="u-close-wrap" v-if="keyword && clearabled && focused" @touchstart="clear"> <view class="u-close-wrap" v-if="keyword && clearabled && focused" @touchstart="clear">
<u-icon class="u-clear-icon" name="close" :size="16" color="#fff" @touchstart="clear"></u-icon> <u-icon class="u-clear-icon" name="close" :size="16" color="#fff" @touchstart="clear"></u-icon>
</view> </view>
</view> </view>
<view :style="[actionStyle]" class="u-action" :class="[showActionBtn || show ? 'u-action-active' : '']" @tap="custom">{{ actionText }}</view> <view :style="[actionStyle]" class="u-action"
:class="[showActionBtn || show ? 'u-action-active' : '']"
@touchstart.stop.prevent="custom"
>{{ actionText }}</view>
</view> </view>
</template> </template>
...@@ -53,6 +56,7 @@ ...@@ -53,6 +56,7 @@
* @property {Boolean} disabled 是否启用输入框(默认false) * @property {Boolean} disabled 是否启用输入框(默认false)
* @property {Boolean} animation 是否开启动画,见上方说明(默认false) * @property {Boolean} animation 是否开启动画,见上方说明(默认false)
* @property {String} value 输入框初始值 * @property {String} value 输入框初始值
* @property {Boolean} input-style input输入框的样式,可以定义文字颜色,大小等,对象形式
* @property {String Number} height 输入框高度,单位rpx(默认64) * @property {String Number} height 输入框高度,单位rpx(默认64)
* @event {Function} change 输入框内容发生变化时触发 * @event {Function} change 输入框内容发生变化时触发
* @event {Function} search 用户确定搜索时触发,用户按回车键,或者手机键盘右下角的"搜索"键时触发 * @event {Function} search 用户确定搜索时触发,用户按回车键,或者手机键盘右下角的"搜索"键时触发
...@@ -133,6 +137,13 @@ export default { ...@@ -133,6 +137,13 @@ export default {
height: { height: {
type: [Number, String], type: [Number, String],
default: 64 default: 64
},
// input输入框的样式,可以定义文字颜色,大小等,对象形式
inputStyle: {
type: Object,
default() {
return {}
}
} }
}, },
data() { data() {
...@@ -198,11 +209,13 @@ export default { ...@@ -198,11 +209,13 @@ export default {
this.focused = true; this.focused = true;
// 开启右侧搜索按钮展开的动画效果 // 开启右侧搜索按钮展开的动画效果
if (this.animation && this.showAction) this.show = true; if (this.animation && this.showAction) this.show = true;
this.$emit('focus', this.keyword);
}, },
// 失去焦点 // 失去焦点
blur() { blur() {
this.focused = false; this.focused = false;
this.show = false; this.show = false;
this.$emit('blur', this.keyword);
} }
} }
}; };
......
<template>
<view class="u-slider" @tap="onClick" :class="[disabled ? 'u-slider--disabled' : '']" :style="{
backgroundColor: inactiveColor
}">
<view
class="u-slider__gap"
:style="[
barStyle,
{
height: height + 'rpx',
backgroundColor: activeColor
}
]"
>
<view class="u-slider__button-wrap" @touchstart="onTouchStart"
@touchmove="onTouchMove" @touchend="onTouchEnd"
@touchcancel="onTouchEnd">
<slot v-if="useSlot"/>
<view v-else class="u-slider__button" :style="[blockStyle, {
height: blockWidth + 'rpx',
width: blockWidth + 'rpx'
}]"></view>
</view>
</view>
</view>
</template>
<script>
/**
* slider 滑块选择器
* @tutorial https://uviewui.com/components/slider.html
* @property {Number | String} value 滑块默认值(默认0)
* @property {Number | String} min 最小值(默认0)
* @property {Number | String} max 最大值(默认100)
* @property {Number | String} step 步长(默认1)
* @property {Number | String} blockWidth 滑块宽度,高等于宽(20)
* @property {Number | String} height 滑块条高度,单位rpx(默认6)
* @property {String} inactiveColor 底部条背景颜色(默认#c0c4cc)
* @property {String} activeColor 底部选择部分颜色(默认#2979ff)
* @property {String} blockColor 滑块颜色(默认#ffffff)
* @property {Object} blockStyle 给滑块自定义样式,对象形式
* @property {Boolean} disabled 是否禁用滑块(默认为false)
* @property {Boolean} useSlot 是否使用slot传入自定义滑块(默认为false)
* @event {Function} start 滑动触发
* @event {Function} moving 正在滑动中
* @event {Function} end 滑动结束
* @example <u-slider v-model="value" />
*/
export default {
name: 'u-slider',
props: {
// 当前进度百分比值,范围0-100
value: {
type: [Number, String],
default: 0
},
// 是否禁用滑块
disabled: {
type: Boolean,
default: false
},
// 滑块宽度,高等于宽,单位rpx
blockWidth: {
type: [Number, String],
default: 20
},
// 最小值
min: {
type: [Number, String],
default: 0
},
// 最大值
max: {
type: [Number, String],
default: 100
},
// 步进值
step: {
type: [Number, String],
default: 1
},
// 滑块条高度,单位rpx
height: {
type: [Number, String],
default: 6
},
// 进度条的激活部分颜色
activeColor: {
type: String,
default: '#2979ff'
},
// 进度条的背景颜色
inactiveColor: {
type: String,
default: '#c0c4cc'
},
// 滑块的背景颜色
blockColor: {
type: String,
default: '#ffffff'
},
// 用户对滑块的自定义颜色
blockStyle: {
type: Object,
default() {
return {};
}
},
// 是否传入自定义的按钮slot
useSlot: {
type: Boolean,
default: false
}
},
data() {
return {
startX: 0,
status: 'end',
newValue: 0,
distanceX: 0,
startValue: 0,
barStyle: {},
sliderRect: {
left: 0,
width: 0
}
};
},
watch: {
value(n) {
// 只有在非滑动状态时,才可以通过value更新滑块值,这里监听,是为了让用户触发
if(this.status == 'end') this.updateValue(this.value, false);
}
},
created() {
this.updateValue(this.value, false);
},
mounted() {
// 获取滑块条的尺寸信息
this.$uGetRect('.u-slider').then(rect => {
this.sliderRect = rect;
});
},
methods: {
onTouchStart(event) {
if (this.disabled) return;
this.startX = 0;
// 触摸点集
let touches = event.touches[0];
// 触摸点到屏幕左边的距离
this.startX = touches.clientX;
// 此处的this.value虽为props值,但是通过$emit('input')进行了修改
this.startValue = this.format(this.value);
// 标示当前的状态为开始触摸滑动
this.status = 'start';
},
onTouchMove(event) {
if (this.disabled) return;
// 连续触摸的过程会一直触发本方法,但只有手指触发且移动了才被认为是拖动了,才发出事件
// 触摸后第一次移动已经将status设置为moving状态,故触摸第二次移动不会触发本事件
if (this.status == 'start') this.$emit('start');
let touches = event.touches[0];
// 滑块的左边不一定跟屏幕左边接壤,所以需要减去最外层父元素的左边值
this.distanceX = touches.clientX - this.sliderRect.left;
// 获得移动距离对整个滑块的百分比值,此为带有多位小数的值,不能用此更新视图
// 否则造成通信阻塞,需要每改变一个step值时修改一次视图
this.newValue = (this.distanceX / this.sliderRect.width) * 100;
this.status = 'moving';
this.updateValue(this.newValue, true);
},
onTouchEnd() {
if (this.disabled) return;
this.status = 'end';
if (this.status === 'moving') {
this.updateValue(this.newValue, false);
this.$emit('end');
}
},
updateValue(value, drag) {
// 去掉小数部分,同时也是对step步进的处理
const width = this.format(value);
// 设置移动的百分比值
let barStyle = {
width: width + '%'
};
// 移动期间无需过渡动画
if (drag == true) {
barStyle.transition = 'none';
} else {
// 非移动期间,删掉对过渡为空的声明,让css中的声明起效
delete barStyle.transition;
}
// 修改value值
this.$emit('input', width);
this.barStyle = barStyle;
},
format(value) {
// 将小数变成整数,为了减少对视图的更新,造成视图层与逻辑层的阻塞
return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step;
},
onClick(event) {
if (this.disabled) return;
// 直接点击滑块的情况,计算方式与onTouchMove方法相同
const value = ((event.detail.x - this.sliderRect.left) / this.sliderRect.width) * 100;
this.updateValue(value, false);
}
}
};
</script>
<style lang="scss" scoped>
.u-slider {
position: relative;
border-radius: 999px;
border-radius: 999px;
background-color: #ebedf0;
}
.u-slider:before {
position: absolute;
right: 0;
left: 0;
content: '';
top: -8px;
bottom: -8px;
z-index: -1;
}
.u-slider__gap {
position: relative;
border-radius: inherit;
transition: width 0.2s;
transition: width 0.2s;
background-color: #1989fa;
}
.u-slider__button {
width: 24px;
height: 24px;
border-radius: 50%;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
background-color: #fff;
cursor: pointer;
}
.u-slider__button-wrap {
position: absolute;
top: 50%;
right: 0;
transform: translate3d(50%, -50%, 0);
}
.u-slider--disabled {
opacity: 0.5;
}
</style>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<view class="u-swiper-wrap" :style="{ <view class="u-swiper-wrap" :style="{
borderRadius: `${borderRadius}rpx`, borderRadius: `${borderRadius}rpx`,
}"> }">
<swiper @change="change" @animationfinish="animationfinish" :current="current" :interval="interval" :circular="circular" :duration="duration" :autoplay="autoplay" <swiper @change="change" @animationfinish="animationfinish" :interval="interval" :circular="circular" :duration="duration" :autoplay="autoplay"
:previous-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'" :next-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'" :previous-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'" :next-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'"
:style="{ :style="{
height: height + 'rpx' height: height + 'rpx'
...@@ -180,14 +180,13 @@ ...@@ -180,14 +180,13 @@
this.$emit('click', index); this.$emit('click', index);
}, },
change(e) { change(e) {
// #ifdef MP-TOUTIAO
this.current = e.detail.current; this.current = e.detail.current;
// #endif
}, },
// 头条小程序不支持animationfinish事件,改由change事件 // 头条小程序不支持animationfinish事件,改由change事件
animationfinish() { // 暂不监听此事件,因为不再给swiper绑定current属性
animationfinish(e) {
// #ifndef MP-TOUTIAO // #ifndef MP-TOUTIAO
this.current = e.detail.current; // this.current = e.detail.current;
// #endif // #endif
} }
} }
......
...@@ -74,16 +74,25 @@ u-icon { ...@@ -74,16 +74,25 @@ u-icon {
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
} }
.u-line-2, .u-line-3 { .u-line-3 {
-webkit-line-clamp: 3;
}
.u-line-4 {
-webkit-line-clamp: 4;
}
.u-line-5 {
-webkit-line-clamp: 5;
}
.u-line-2, .u-line-3, .u-line-4, .u-line-5 {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: -webkit-box; // 弹性伸缩盒 display: -webkit-box; // 弹性伸缩盒
-webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式 -webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式
} }
.u-line-3 {
-webkit-line-clamp: 3;
}
/* end--文本行数限制--end */ /* end--文本行数限制--end */
......
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