提交 f6ceab9b authored 作者: 杨斌基's avatar 杨斌基

fix(uview-ui): 在 macOS 上 easycom 不识别出这些组件,导致 Vue 报错组件未注册

上级 6fe0ee09
MIT License MIT License
Copyright (c) 2020 www.uviewui.com Copyright (c) 2020 www.uviewui.com
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
\ No newline at end of file
<template> <template>
<uvForm <uvForm
ref="uForm" ref="uForm"
:model="model" :model="model"
:rules="rules" :rules="rules"
:errorType="errorType" :errorType="errorType"
:borderBottom="borderBottom" :borderBottom="borderBottom"
:labelPosition="labelPosition" :labelPosition="labelPosition"
:labelWidth="labelWidth" :labelWidth="labelWidth"
:labelAlign="labelAlign" :labelAlign="labelAlign"
:labelStyle="labelStyle" :labelStyle="labelStyle"
:customStyle="customStyle" :customStyle="customStyle"
> >
<slot /> <slot />
</uvForm> </uvForm>
</template> </template>
<script> <script>
/** /**
* 此组件存在的理由是,在nvue下,u-form被uni-app官方占用了,u-form在nvue中相当于form组件 * 此组件存在的理由是,在nvue下,u-form被uni-app官方占用了,u-form在nvue中相当于form组件
* 所以在nvue下,取名为u--form,内部其实还是u-form.vue,只不过做一层中转 * 所以在nvue下,取名为u--form,内部其实还是u-form.vue,只不过做一层中转
*/ */
import uvForm from '../u-form/u-form.vue'; import uvForm from '../u-form/u-form.vue';
import props from '../u-form/props.js' import props from '../u-form/props.js'
export default { export default {
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
name: 'u-form', name: 'u-form',
// #endif // #endif
// #ifndef MP-WEIXIN // #ifndef MP-WEIXIN
name: 'u--form', name: 'u--form',
// #endif // #endif
mixins: [uni.$u.mpMixin, props, uni.$u.mixin], mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: { components: {
uvForm uvForm
}, },
created() { created() {
this.children = [] this.children = []
}, },
methods: { methods: {
// 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则 // 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
setRules(rules) { setRules(rules) {
this.$refs.uForm.setRules(rules) this.$refs.uForm.setRules(rules)
}, },
validate() { validate() {
/** /**
* 在微信小程序中,通过this.$parent拿到的父组件是u--form,而不是其内嵌的u-form * 在微信小程序中,通过this.$parent拿到的父组件是u--form,而不是其内嵌的u-form
* 导致在u-form组件中,拿不到对应的children数组,从而校验无效,所以这里每次调用u-form组件中的 * 导致在u-form组件中,拿不到对应的children数组,从而校验无效,所以这里每次调用u-form组件中的
* 对应方法的时候,在小程序中都先将u--form的children赋值给u-form中的children * 对应方法的时候,在小程序中都先将u--form的children赋值给u-form中的children
*/ */
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
this.setMpData() this.setMpData()
// #endif // #endif
return this.$refs.uForm.validate() return this.$refs.uForm.validate()
}, },
validateField(value, callback) { validateField(value, callback) {
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
this.setMpData() this.setMpData()
// #endif // #endif
return this.$refs.uForm.validateField(value, callback) return this.$refs.uForm.validateField(value, callback)
}, },
resetFields() { resetFields() {
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
this.setMpData() this.setMpData()
// #endif // #endif
return this.$refs.uForm.resetFields() return this.$refs.uForm.resetFields()
}, },
clearValidate(props) { clearValidate(props) {
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
this.setMpData() this.setMpData()
// #endif // #endif
return this.$refs.uForm.clearValidate(props) return this.$refs.uForm.clearValidate(props)
}, },
setMpData() { setMpData() {
this.$refs.uForm.children = this.children this.$refs.uForm.children = this.children
} }
}, },
} }
</script> </script>
<template> <template>
<uvImage <uvImage
:src="src" :src="src"
:mode="mode" :mode="mode"
:width="width" :width="width"
:height="height" :height="height"
:shape="shape" :shape="shape"
:radius="radius" :radius="radius"
:lazyLoad="lazyLoad" :lazyLoad="lazyLoad"
:showMenuByLongpress="showMenuByLongpress" :showMenuByLongpress="showMenuByLongpress"
:loadingIcon="loadingIcon" :loadingIcon="loadingIcon"
:errorIcon="errorIcon" :errorIcon="errorIcon"
:showLoading="showLoading" :showLoading="showLoading"
:showError="showError" :showError="showError"
:fade="fade" :fade="fade"
:webp="webp" :webp="webp"
:duration="duration" :duration="duration"
:bgColor="bgColor" :bgColor="bgColor"
:customStyle="customStyle" :customStyle="customStyle"
@click="$emit('click')" @click="$emit('click')"
@error="$emit('error')" @error="$emit('error')"
@load="$emit('load')" @load="$emit('load')"
> >
<template v-slot:loading> <template v-slot:loading>
<slot name="loading"></slot> <slot name="loading"></slot>
...@@ -27,21 +27,21 @@ ...@@ -27,21 +27,21 @@
<template v-slot:error> <template v-slot:error>
<slot name="error"></slot> <slot name="error"></slot>
</template> </template>
</uvImage> </uvImage>
</template> </template>
<script> <script>
/** /**
* 此组件存在的理由是,在nvue下,u-image被uni-app官方占用了,u-image在nvue中相当于image组件 * 此组件存在的理由是,在nvue下,u-image被uni-app官方占用了,u-image在nvue中相当于image组件
* 所以在nvue下,取名为u--image,内部其实还是u-iamge.vue,只不过做一层中转 * 所以在nvue下,取名为u--image,内部其实还是u-iamge.vue,只不过做一层中转
*/ */
import uvImage from '../u-image/u-image.vue'; import uvImage from '../u-image/u-image.vue';
import props from '../u-image/props.js'; import props from '../u-image/props.js';
export default { export default {
name: 'u--image', name: 'u--image',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin], mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: { components: {
uvImage uvImage
}, },
} }
</script> </script>
\ No newline at end of file
<template> <template>
<uvInput <uvInput
:value="value" :value="value"
:type="type" :type="type"
:fixed="fixed" :fixed="fixed"
:disabled="disabled" :disabled="disabled"
:disabledColor="disabledColor" :disabledColor="disabledColor"
:clearable="clearable" :clearable="clearable"
:password="password" :password="password"
:maxlength="maxlength" :maxlength="maxlength"
:placeholder="placeholder" :placeholder="placeholder"
:placeholderClass="placeholderClass" :placeholderClass="placeholderClass"
:placeholderStyle="placeholderStyle" :placeholderStyle="placeholderStyle"
:showWordLimit="showWordLimit" :showWordLimit="showWordLimit"
:confirmType="confirmType" :confirmType="confirmType"
:confirmHold="confirmHold" :confirmHold="confirmHold"
:holdKeyboard="holdKeyboard" :holdKeyboard="holdKeyboard"
:focus="focus" :focus="focus"
:autoBlur="autoBlur" :autoBlur="autoBlur"
:disableDefaultPadding="disableDefaultPadding" :disableDefaultPadding="disableDefaultPadding"
:cursor="cursor" :cursor="cursor"
:cursorSpacing="cursorSpacing" :cursorSpacing="cursorSpacing"
:selectionStart="selectionStart" :selectionStart="selectionStart"
:selectionEnd="selectionEnd" :selectionEnd="selectionEnd"
:adjustPosition="adjustPosition" :adjustPosition="adjustPosition"
:inputAlign="inputAlign" :inputAlign="inputAlign"
:fontSize="fontSize" :fontSize="fontSize"
:color="color" :color="color"
:prefixIcon="prefixIcon" :prefixIcon="prefixIcon"
:suffixIcon="suffixIcon" :suffixIcon="suffixIcon"
:suffixIconStyle="suffixIconStyle" :suffixIconStyle="suffixIconStyle"
:prefixIconStyle="prefixIconStyle" :prefixIconStyle="prefixIconStyle"
:border="border" :border="border"
:readonly="readonly" :readonly="readonly"
:shape="shape" :shape="shape"
:customStyle="customStyle" :customStyle="customStyle"
:formatter="formatter" :formatter="formatter"
:ignoreCompositionEvent="ignoreCompositionEvent" :ignoreCompositionEvent="ignoreCompositionEvent"
@focus="$emit('focus')" @focus="$emit('focus')"
@blur="e => $emit('blur', e)" @blur="e => $emit('blur', e)"
@keyboardheightchange="$emit('keyboardheightchange')" @keyboardheightchange="$emit('keyboardheightchange')"
@change="e => $emit('change', e)" @change="e => $emit('change', e)"
@input="e => $emit('input', e)" @input="e => $emit('input', e)"
@confirm="e => $emit('confirm', e)" @confirm="e => $emit('confirm', e)"
@clear="$emit('clear')" @clear="$emit('clear')"
@click="$emit('click')" @click="$emit('click')"
> >
<!-- #ifdef MP --> <!-- #ifdef MP -->
<slot name="prefix"></slot> <slot name="prefix"></slot>
<slot name="suffix"></slot> <slot name="suffix"></slot>
<!-- #endif --> <!-- #endif -->
<!-- #ifndef MP --> <!-- #ifndef MP -->
<slot name="prefix" slot="prefix"></slot> <slot name="prefix" slot="prefix"></slot>
<slot name="suffix" slot="suffix"></slot> <slot name="suffix" slot="suffix"></slot>
<!-- #endif --> <!-- #endif -->
</uvInput> </uvInput>
</template> </template>
<script> <script>
/** /**
* 此组件存在的理由是,在nvue下,u-input被uni-app官方占用了,u-input在nvue中相当于input组件 * 此组件存在的理由是,在nvue下,u-input被uni-app官方占用了,u-input在nvue中相当于input组件
* 所以在nvue下,取名为u--input,内部其实还是u-input.vue,只不过做一层中转 * 所以在nvue下,取名为u--input,内部其实还是u-input.vue,只不过做一层中转
*/ */
import uvInput from '../u-input/u-input.vue'; import uvInput from '../u-input/u-input.vue';
import props from '../u-input/props.js' import props from '../u-input/props.js'
export default { export default {
name: 'u--input', name: 'u--input',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin], mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: { components: {
uvInput uvInput
}, },
} }
</script> </script>
\ No newline at end of file
<template> <template>
<uvText <uvText
:type="type" :type="type"
:show="show" :show="show"
:text="text" :text="text"
:prefixIcon="prefixIcon" :prefixIcon="prefixIcon"
:suffixIcon="suffixIcon" :suffixIcon="suffixIcon"
:mode="mode" :mode="mode"
:href="href" :href="href"
:format="format" :format="format"
:call="call" :call="call"
:openType="openType" :openType="openType"
:bold="bold" :bold="bold"
:block="block" :block="block"
:lines="lines" :lines="lines"
:color="color" :color="color"
:decoration="decoration" :decoration="decoration"
:size="size" :size="size"
:iconStyle="iconStyle" :iconStyle="iconStyle"
:margin="margin" :margin="margin"
:lineHeight="lineHeight" :lineHeight="lineHeight"
:align="align" :align="align"
:wordWrap="wordWrap" :wordWrap="wordWrap"
:customStyle="customStyle" :customStyle="customStyle"
@click="$emit('click')" @click="$emit('click')"
></uvText> ></uvText>
</template> </template>
<script> <script>
/** /**
* 此组件存在的理由是,在nvue下,u-text被uni-app官方占用了,u-text在nvue中相当于input组件 * 此组件存在的理由是,在nvue下,u-text被uni-app官方占用了,u-text在nvue中相当于input组件
* 所以在nvue下,取名为u--input,内部其实还是u-text.vue,只不过做一层中转 * 所以在nvue下,取名为u--input,内部其实还是u-text.vue,只不过做一层中转
* 不使用v-bind="$attrs",而是分开独立写传参,是因为微信小程序不支持此写法 * 不使用v-bind="$attrs",而是分开独立写传参,是因为微信小程序不支持此写法
*/ */
import uvText from "../u-text/u-text.vue"; import uvText from "../u-text/u-text.vue";
import props from "../u-text/props.js"; import props from "../u-text/props.js";
export default { export default {
name: "u--text", name: "u--text",
mixins: [uni.$u.mpMixin, props, uni.$u.mixin], mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: { components: {
uvText, uvText,
}, },
}; };
</script> </script>
<template> <template>
<uvTextarea <uvTextarea
:value="value" :value="value"
:placeholder="placeholder" :placeholder="placeholder"
:height="height" :height="height"
:confirmType="confirmType" :confirmType="confirmType"
:disabled="disabled" :disabled="disabled"
:count="count" :count="count"
:focus="focus" :focus="focus"
:autoHeight="autoHeight" :autoHeight="autoHeight"
:fixed="fixed" :fixed="fixed"
:cursorSpacing="cursorSpacing" :cursorSpacing="cursorSpacing"
:cursor="cursor" :cursor="cursor"
:showConfirmBar="showConfirmBar" :showConfirmBar="showConfirmBar"
:selectionStart="selectionStart" :selectionStart="selectionStart"
:selectionEnd="selectionEnd" :selectionEnd="selectionEnd"
:adjustPosition="adjustPosition" :adjustPosition="adjustPosition"
:disableDefaultPadding="disableDefaultPadding" :disableDefaultPadding="disableDefaultPadding"
:holdKeyboard="holdKeyboard" :holdKeyboard="holdKeyboard"
:maxlength="maxlength" :maxlength="maxlength"
:border="border" :border="border"
:customStyle="customStyle" :customStyle="customStyle"
:formatter="formatter" :formatter="formatter"
:ignoreCompositionEvent="ignoreCompositionEvent" :ignoreCompositionEvent="ignoreCompositionEvent"
@focus="e => $emit('focus')" @focus="e => $emit('focus')"
@blur="e => $emit('blur')" @blur="e => $emit('blur')"
@linechange="e => $emit('linechange', e)" @linechange="e => $emit('linechange', e)"
@confirm="e => $emit('confirm')" @confirm="e => $emit('confirm')"
@input="e => $emit('input', e)" @input="e => $emit('input', e)"
@keyboardheightchange="e => $emit('keyboardheightchange')" @keyboardheightchange="e => $emit('keyboardheightchange')"
></uvTextarea> ></uvTextarea>
</template> </template>
<script> <script>
/** /**
* 此组件存在的理由是,在nvue下,u--textarea被uni-app官方占用了,u-textarea在nvue中相当于textarea组件 * 此组件存在的理由是,在nvue下,u--textarea被uni-app官方占用了,u-textarea在nvue中相当于textarea组件
* 所以在nvue下,取名为u--textarea,内部其实还是u-textarea.vue,只不过做一层中转 * 所以在nvue下,取名为u--textarea,内部其实还是u-textarea.vue,只不过做一层中转
*/ */
import uvTextarea from '../u-textarea/u-textarea.vue'; import uvTextarea from '../u-textarea/u-textarea.vue';
import props from '../u-textarea/props.js' import props from '../u-textarea/props.js'
export default { export default {
name: 'u--textarea', name: 'u--textarea',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin], mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: { components: {
uvTextarea uvTextarea
}, },
} }
</script> </script>
export default { export default {
props: { props: {
// 显示文字 // 显示文字
title: { title: {
type: String, type: String,
default: uni.$u.props.alert.title default: uni.$u.props.alert.title
}, },
// 主题,success/warning/info/error // 主题,success/warning/info/error
type: { type: {
type: String, type: String,
default: uni.$u.props.alert.type default: uni.$u.props.alert.type
}, },
// 辅助性文字 // 辅助性文字
description: { description: {
type: String, type: String,
default: uni.$u.props.alert.description default: uni.$u.props.alert.description
}, },
// 是否可关闭 // 是否可关闭
closable: { closable: {
type: Boolean, type: Boolean,
default: uni.$u.props.alert.closable default: uni.$u.props.alert.closable
}, },
// 是否显示图标 // 是否显示图标
showIcon: { showIcon: {
type: Boolean, type: Boolean,
default: uni.$u.props.alert.showIcon default: uni.$u.props.alert.showIcon
}, },
// 浅或深色调,light-浅色,dark-深色 // 浅或深色调,light-浅色,dark-深色
effect: { effect: {
type: String, type: String,
default: uni.$u.props.alert.effect default: uni.$u.props.alert.effect
}, },
// 文字是否居中 // 文字是否居中
center: { center: {
type: Boolean, type: Boolean,
default: uni.$u.props.alert.center default: uni.$u.props.alert.center
}, },
// 字体大小 // 字体大小
fontSize: { fontSize: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.alert.fontSize default: uni.$u.props.alert.fontSize
} }
} }
} }
$u-button-active-opacity:0.75 !default; $u-button-active-opacity:0.75 !default;
$u-button-loading-text-margin-left:4px !default; $u-button-loading-text-margin-left:4px !default;
$u-button-text-color: #FFFFFF !default; $u-button-text-color: #FFFFFF !default;
$u-button-text-plain-error-color:$u-error !default; $u-button-text-plain-error-color:$u-error !default;
$u-button-text-plain-warning-color:$u-warning !default; $u-button-text-plain-warning-color:$u-warning !default;
$u-button-text-plain-success-color:$u-success !default; $u-button-text-plain-success-color:$u-success !default;
$u-button-text-plain-info-color:$u-info !default; $u-button-text-plain-info-color:$u-info !default;
$u-button-text-plain-primary-color:$u-primary !default; $u-button-text-plain-primary-color:$u-primary !default;
.u-button { .u-button {
&--active { &--active {
opacity: $u-button-active-opacity; opacity: $u-button-active-opacity;
} }
&--active--plain { &--active--plain {
background-color: rgb(217, 217, 217); background-color: rgb(217, 217, 217);
} }
&__loading-text { &__loading-text {
margin-left:$u-button-loading-text-margin-left; margin-left:$u-button-loading-text-margin-left;
} }
&__text, &__text,
&__loading-text { &__loading-text {
color:$u-button-text-color; color:$u-button-text-color;
} }
&__text--plain--error { &__text--plain--error {
color:$u-button-text-plain-error-color; color:$u-button-text-plain-error-color;
} }
&__text--plain--warning { &__text--plain--warning {
color:$u-button-text-plain-warning-color; color:$u-button-text-plain-warning-color;
} }
&__text--plain--success{ &__text--plain--success{
color:$u-button-text-plain-success-color; color:$u-button-text-plain-success-color;
} }
&__text--plain--info { &__text--plain--info {
color:$u-button-text-plain-info-color; color:$u-button-text-plain-info-color;
} }
&__text--plain--primary { &__text--plain--primary {
color:$u-button-text-plain-primary-color; color:$u-button-text-plain-primary-color;
} }
} }
\ No newline at end of file
// nvue下hover-class无效 // nvue下hover-class无效
$u-button-before-top:50% !default; $u-button-before-top:50% !default;
$u-button-before-left:50% !default; $u-button-before-left:50% !default;
$u-button-before-width:100% !default; $u-button-before-width:100% !default;
$u-button-before-height:100% !default; $u-button-before-height:100% !default;
$u-button-before-transform:translate(-50%, -50%) !default; $u-button-before-transform:translate(-50%, -50%) !default;
$u-button-before-opacity:0 !default; $u-button-before-opacity:0 !default;
$u-button-before-background-color:#000 !default; $u-button-before-background-color:#000 !default;
$u-button-before-border-color:#000 !default; $u-button-before-border-color:#000 !default;
$u-button-active-before-opacity:.15 !default; $u-button-active-before-opacity:.15 !default;
$u-button-icon-margin-left:4px !default; $u-button-icon-margin-left:4px !default;
$u-button-plain-u-button-info-color:$u-info; $u-button-plain-u-button-info-color:$u-info;
$u-button-plain-u-button-success-color:$u-success; $u-button-plain-u-button-success-color:$u-success;
$u-button-plain-u-button-error-color:$u-error; $u-button-plain-u-button-error-color:$u-error;
$u-button-plain-u-button-warning-color:$u-error; $u-button-plain-u-button-warning-color:$u-error;
.u-button { .u-button {
width: 100%; width: 100%;
...@@ -21,60 +21,60 @@ $u-button-plain-u-button-warning-color:$u-error; ...@@ -21,60 +21,60 @@ $u-button-plain-u-button-warning-color:$u-error;
white-space: nowrap; white-space: nowrap;
line-height: 1; line-height: 1;
} }
&:before { &:before {
position: absolute; position: absolute;
top:$u-button-before-top; top:$u-button-before-top;
left:$u-button-before-left; left:$u-button-before-left;
width:$u-button-before-width; width:$u-button-before-width;
height:$u-button-before-height; height:$u-button-before-height;
border: inherit; border: inherit;
border-radius: inherit; border-radius: inherit;
transform:$u-button-before-transform; transform:$u-button-before-transform;
opacity:$u-button-before-opacity; opacity:$u-button-before-opacity;
content: " "; content: " ";
background-color:$u-button-before-background-color; background-color:$u-button-before-background-color;
border-color:$u-button-before-border-color; border-color:$u-button-before-border-color;
} }
&--active { &--active {
&:before { &:before {
opacity: .15 opacity: .15
} }
} }
&__icon+&__text:not(:empty), &__icon+&__text:not(:empty),
&__loading-text { &__loading-text {
margin-left:$u-button-icon-margin-left; margin-left:$u-button-icon-margin-left;
} }
&--plain { &--plain {
&.u-button--primary { &.u-button--primary {
color: $u-primary; color: $u-primary;
} }
} }
&--plain { &--plain {
&.u-button--info { &.u-button--info {
color:$u-button-plain-u-button-info-color; color:$u-button-plain-u-button-info-color;
} }
} }
&--plain { &--plain {
&.u-button--success { &.u-button--success {
color:$u-button-plain-u-button-success-color; color:$u-button-plain-u-button-success-color;
} }
} }
&--plain { &--plain {
&.u-button--error { &.u-button--error {
color:$u-button-plain-u-button-error-color; color:$u-button-plain-u-button-error-color;
} }
} }
&--plain { &--plain {
&.u-button--warning { &.u-button--warning {
color:$u-button-plain-u-button-warning-color; color:$u-button-plain-u-button-warning-color;
} }
} }
} }
<template> <template>
<view class="u-calendar-header u-border-bottom"> <view class="u-calendar-header u-border-bottom">
<text <text
class="u-calendar-header__title" class="u-calendar-header__title"
v-if="showTitle" v-if="showTitle"
>{{ title }}</text> >{{ title }}</text>
<text <text
class="u-calendar-header__subtitle" class="u-calendar-header__subtitle"
v-if="showSubtitle" v-if="showSubtitle"
>{{ subtitle }}</text> >{{ subtitle }}</text>
<view class="u-calendar-header__weekdays"> <view class="u-calendar-header__weekdays">
<text class="u-calendar-header__weekdays__weekday"></text> <text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text> <text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text> <text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text> <text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text> <text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text> <text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text> <text class="u-calendar-header__weekdays__weekday"></text>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: 'u-calendar-header', name: 'u-calendar-header',
mixins: [uni.$u.mpMixin, uni.$u.mixin], mixins: [uni.$u.mpMixin, uni.$u.mixin],
props: { props: {
// 标题 // 标题
title: { title: {
type: String, type: String,
default: '' default: ''
}, },
// 副标题 // 副标题
subtitle: { subtitle: {
type: String, type: String,
default: '' default: ''
}, },
// 是否显示标题 // 是否显示标题
showTitle: { showTitle: {
type: Boolean, type: Boolean,
default: true default: true
}, },
// 是否显示副标题 // 是否显示副标题
showSubtitle: { showSubtitle: {
type: Boolean, type: Boolean,
default: true default: true
}, },
}, },
data() { data() {
return { return {
} }
}, },
methods: { methods: {
name() { name() {
} }
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../../libs/css/components.scss"; @import "../../libs/css/components.scss";
.u-calendar-header { .u-calendar-header {
padding-bottom: 4px; padding-bottom: 4px;
&__title { &__title {
font-size: 16px; font-size: 16px;
color: $u-main-color; color: $u-main-color;
text-align: center; text-align: center;
height: 42px; height: 42px;
line-height: 42px; line-height: 42px;
font-weight: bold; font-weight: bold;
} }
&__subtitle { &__subtitle {
font-size: 14px; font-size: 14px;
color: $u-main-color; color: $u-main-color;
height: 40px; height: 40px;
text-align: center; text-align: center;
line-height: 40px; line-height: 40px;
font-weight: bold; font-weight: bold;
} }
&__weekdays { &__weekdays {
@include flex; @include flex;
justify-content: space-between; justify-content: space-between;
&__weekday { &__weekday {
font-size: 13px; font-size: 13px;
color: $u-main-color; color: $u-main-color;
line-height: 30px; line-height: 30px;
flex: 1; flex: 1;
text-align: center; text-align: center;
} }
} }
} }
</style> </style>
export default { export default {
methods: { methods: {
// 设置月份数据 // 设置月份数据
setMonth() { setMonth() {
// 月初是周几 // 月初是周几
const day = dayjs(this.date).date(1).day() const day = dayjs(this.date).date(1).day()
const start = day == 0 ? 6 : day - 1 const start = day == 0 ? 6 : day - 1
// 本月天数 // 本月天数
const days = dayjs(this.date).endOf('month').format('D') const days = dayjs(this.date).endOf('month').format('D')
// 上个月天数 // 上个月天数
const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D') const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D')
// 日期数据 // 日期数据
const arr = [] const arr = []
// 清空表格 // 清空表格
this.month = [] this.month = []
// 添加上月数据 // 添加上月数据
arr.push( arr.push(
...new Array(start).fill(1).map((e, i) => { ...new Array(start).fill(1).map((e, i) => {
const day = prevDays - start + i + 1 const day = prevDays - start + i + 1
return { return {
value: day, value: day,
disabled: true, disabled: true,
date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD') date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD')
} }
}) })
) )
// 添加本月数据 // 添加本月数据
arr.push( arr.push(
...new Array(days - 0).fill(1).map((e, i) => { ...new Array(days - 0).fill(1).map((e, i) => {
const day = i + 1 const day = i + 1
return { return {
value: day, value: day,
date: dayjs(this.date).date(day).format('YYYY-MM-DD') date: dayjs(this.date).date(day).format('YYYY-MM-DD')
} }
}) })
) )
// 添加下个月 // 添加下个月
arr.push( arr.push(
...new Array(42 - days - start).fill(1).map((e, i) => { ...new Array(42 - days - start).fill(1).map((e, i) => {
const day = i + 1 const day = i + 1
return { return {
value: day, value: day,
disabled: true, disabled: true,
date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD') date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD')
} }
}) })
) )
// 分割数组 // 分割数组
for (let n = 0; n < arr.length; n += 7) { for (let n = 0; n < arr.length; n += 7) {
this.month.push( this.month.push(
arr.slice(n, n + 7).map((e, i) => { arr.slice(n, n + 7).map((e, i) => {
e.index = i + n e.index = i + n
// 自定义信息 // 自定义信息
const custom = this.customList.find((c) => c.date == e.date) const custom = this.customList.find((c) => c.date == e.date)
// 农历 // 农历
if (this.lunar) { if (this.lunar) {
const { const {
IDayCn, IDayCn,
IMonthCn IMonthCn
} = this.getLunar(e.date) } = this.getLunar(e.date)
e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn
} }
return { return {
...e, ...e,
...custom ...custom
} }
}) })
) )
} }
} }
} }
} }
<template> <template>
<view class="u-count-down"> <view class="u-count-down">
<slot> <slot>
<text class="u-count-down__text">{{ formattedTime }}</text> <text class="u-count-down__text">{{ formattedTime }}</text>
</slot> </slot>
</view> </view>
</template> </template>
<script> <script>
import props from './props.js'; import props from './props.js';
import { import {
isSameSecond, isSameSecond,
parseFormat, parseFormat,
parseTimeData parseTimeData
} from './utils'; } from './utils';
/** /**
* u-count-down 倒计时 * u-count-down 倒计时
* @description 该组件一般使用于某个活动的截止时间上,通过数字的变化,给用户明确的时间感受,提示用户进行某一个行为操作。 * @description 该组件一般使用于某个活动的截止时间上,通过数字的变化,给用户明确的时间感受,提示用户进行某一个行为操作。
* @tutorial https://uviewui.com/components/countDown.html * @tutorial https://uviewui.com/components/countDown.html
* @property {String | Number} time 倒计时时长,单位ms (默认 0 ) * @property {String | Number} time 倒计时时长,单位ms (默认 0 )
* @property {String} format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 (默认 'HH:mm:ss' ) * @property {String} format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 (默认 'HH:mm:ss' )
* @property {Boolean} autoStart 是否自动开始倒计时 (默认 true ) * @property {Boolean} autoStart 是否自动开始倒计时 (默认 true )
* @property {Boolean} millisecond 是否展示毫秒倒计时 (默认 false ) * @property {Boolean} millisecond 是否展示毫秒倒计时 (默认 false )
* @event {Function} finish 倒计时结束时触发 * @event {Function} finish 倒计时结束时触发
* @event {Function} change 倒计时变化时触发 * @event {Function} change 倒计时变化时触发
* @event {Function} start 开始倒计时 * @event {Function} start 开始倒计时
* @event {Function} pause 暂停倒计时 * @event {Function} pause 暂停倒计时
* @event {Function} reset 重设倒计时,若 auto-start 为 true,重设后会自动开始倒计时 * @event {Function} reset 重设倒计时,若 auto-start 为 true,重设后会自动开始倒计时
* @example <u-count-down :time="time"></u-count-down> * @example <u-count-down :time="time"></u-count-down>
*/ */
export default { export default {
name: 'u-count-down', name: 'u-count-down',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props], mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() { data() {
return { return {
timer: null, timer: null,
// 各单位(天,时,分等)剩余时间 // 各单位(天,时,分等)剩余时间
timeData: parseTimeData(0), timeData: parseTimeData(0),
// 格式化后的时间,如"03:23:21" // 格式化后的时间,如"03:23:21"
formattedTime: '0', formattedTime: '0',
// 倒计时是否正在进行中 // 倒计时是否正在进行中
runing: false, runing: false,
endTime: 0, // 结束的毫秒时间戳 endTime: 0, // 结束的毫秒时间戳
remainTime: 0, // 剩余的毫秒时间 remainTime: 0, // 剩余的毫秒时间
} }
}, },
watch: { watch: {
time(n) { time(n) {
this.reset() this.reset()
} }
}, },
mounted() { mounted() {
this.init() this.init()
}, },
methods: { methods: {
init() { init() {
this.reset() this.reset()
}, },
// 开始倒计时 // 开始倒计时
start() { start() {
if (this.runing) return if (this.runing) return
// 标识为进行中 // 标识为进行中
this.runing = true this.runing = true
// 结束时间戳 = 此刻时间戳 + 剩余的时间 // 结束时间戳 = 此刻时间戳 + 剩余的时间
this.endTime = Date.now() + this.remainTime this.endTime = Date.now() + this.remainTime
this.toTick() this.toTick()
}, },
// 根据是否展示毫秒,执行不同操作函数 // 根据是否展示毫秒,执行不同操作函数
toTick() { toTick() {
if (this.millisecond) { if (this.millisecond) {
this.microTick() this.microTick()
} else { } else {
this.macroTick() this.macroTick()
} }
}, },
macroTick() { macroTick() {
this.clearTimeout() this.clearTimeout()
// 每隔一定时间,更新一遍定时器的值 // 每隔一定时间,更新一遍定时器的值
// 同时此定时器的作用也能带来毫秒级的更新 // 同时此定时器的作用也能带来毫秒级的更新
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
// 获取剩余时间 // 获取剩余时间
const remain = this.getRemainTime() const remain = this.getRemainTime()
// 重设剩余时间 // 重设剩余时间
if (!isSameSecond(remain, this.remainTime) || remain === 0) { if (!isSameSecond(remain, this.remainTime) || remain === 0) {
this.setRemainTime(remain) this.setRemainTime(remain)
} }
// 如果剩余时间不为0,则继续检查更新倒计时 // 如果剩余时间不为0,则继续检查更新倒计时
if (this.remainTime !== 0) { if (this.remainTime !== 0) {
this.macroTick() this.macroTick()
} }
}, 30) }, 30)
}, },
microTick() { microTick() {
this.clearTimeout() this.clearTimeout()
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.setRemainTime(this.getRemainTime()) this.setRemainTime(this.getRemainTime())
if (this.remainTime !== 0) { if (this.remainTime !== 0) {
this.microTick() this.microTick()
} }
}, 50) }, 50)
}, },
// 获取剩余的时间 // 获取剩余的时间
getRemainTime() { getRemainTime() {
// 取最大值,防止出现小于0的剩余时间值 // 取最大值,防止出现小于0的剩余时间值
return Math.max(this.endTime - Date.now(), 0) return Math.max(this.endTime - Date.now(), 0)
}, },
// 设置剩余的时间 // 设置剩余的时间
setRemainTime(remain) { setRemainTime(remain) {
this.remainTime = remain this.remainTime = remain
// 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象 // 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象
const timeData = parseTimeData(remain) const timeData = parseTimeData(remain)
this.$emit('change', timeData) this.$emit('change', timeData)
// 得出格式化后的时间 // 得出格式化后的时间
this.formattedTime = parseFormat(this.format, timeData) this.formattedTime = parseFormat(this.format, timeData)
// 如果时间已到,停止倒计时 // 如果时间已到,停止倒计时
if (remain <= 0) { if (remain <= 0) {
this.pause() this.pause()
this.$emit('finish') this.$emit('finish')
} }
}, },
// 重置倒计时 // 重置倒计时
reset() { reset() {
this.pause() this.pause()
this.remainTime = this.time this.remainTime = this.time
this.setRemainTime(this.remainTime) this.setRemainTime(this.remainTime)
if (this.autoStart) { if (this.autoStart) {
this.start() this.start()
} }
}, },
// 暂停倒计时 // 暂停倒计时
pause() { pause() {
this.runing = false; this.runing = false;
this.clearTimeout() this.clearTimeout()
}, },
// 清空定时器 // 清空定时器
clearTimeout() { clearTimeout() {
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = null this.timer = null
} }
}, },
beforeDestroy() { beforeDestroy() {
this.clearTimeout() this.clearTimeout()
} }
} }
</script> </script>
<style <style
lang="scss" lang="scss"
scoped scoped
> >
@import "../../libs/css/components.scss"; @import "../../libs/css/components.scss";
$u-count-down-text-color:$u-content-color !default; $u-count-down-text-color:$u-content-color !default;
$u-count-down-text-font-size:15px !default; $u-count-down-text-font-size:15px !default;
$u-count-down-text-line-height:22px !default; $u-count-down-text-line-height:22px !default;
.u-count-down { .u-count-down {
&__text { &__text {
color: $u-count-down-text-color; color: $u-count-down-text-color;
font-size: $u-count-down-text-font-size; font-size: $u-count-down-text-font-size;
line-height: $u-count-down-text-line-height; line-height: $u-count-down-text-line-height;
} }
} }
</style> </style>
// 补0,如1 -> 01 // 补0,如1 -> 01
function padZero(num, targetLength = 2) { function padZero(num, targetLength = 2) {
let str = `${num}` let str = `${num}`
while (str.length < targetLength) { while (str.length < targetLength) {
str = `0${str}` str = `0${str}`
} }
return str return str
} }
const SECOND = 1000 const SECOND = 1000
const MINUTE = 60 * SECOND const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE const HOUR = 60 * MINUTE
const DAY = 24 * HOUR const DAY = 24 * HOUR
export function parseTimeData(time) { export function parseTimeData(time) {
const days = Math.floor(time / DAY) const days = Math.floor(time / DAY)
const hours = Math.floor((time % DAY) / HOUR) const hours = Math.floor((time % DAY) / HOUR)
const minutes = Math.floor((time % HOUR) / MINUTE) const minutes = Math.floor((time % HOUR) / MINUTE)
const seconds = Math.floor((time % MINUTE) / SECOND) const seconds = Math.floor((time % MINUTE) / SECOND)
const milliseconds = Math.floor(time % SECOND) const milliseconds = Math.floor(time % SECOND)
return { return {
days, days,
hours, hours,
minutes, minutes,
seconds, seconds,
milliseconds milliseconds
} }
} }
export function parseFormat(format, timeData) { export function parseFormat(format, timeData) {
let { let {
days, days,
hours, hours,
minutes, minutes,
seconds, seconds,
milliseconds milliseconds
} = timeData } = timeData
// 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去 // 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去
if (format.indexOf('DD') === -1) { if (format.indexOf('DD') === -1) {
hours += days * 24 hours += days * 24
} else { } else {
// 对天补0 // 对天补0
format = format.replace('DD', padZero(days)) format = format.replace('DD', padZero(days))
} }
// 其他同理于DD的格式化处理方式 // 其他同理于DD的格式化处理方式
if (format.indexOf('HH') === -1) { if (format.indexOf('HH') === -1) {
minutes += hours * 60 minutes += hours * 60
} else { } else {
format = format.replace('HH', padZero(hours)) format = format.replace('HH', padZero(hours))
} }
if (format.indexOf('mm') === -1) { if (format.indexOf('mm') === -1) {
seconds += minutes * 60 seconds += minutes * 60
} else { } else {
format = format.replace('mm', padZero(minutes)) format = format.replace('mm', padZero(minutes))
} }
if (format.indexOf('ss') === -1) { if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000 milliseconds += seconds * 1000
} else { } else {
format = format.replace('ss', padZero(seconds)) format = format.replace('ss', padZero(seconds))
} }
return format.replace('SSS', padZero(milliseconds, 3)) return format.replace('SSS', padZero(milliseconds, 3))
} }
export function isSameSecond(time1, time2) { export function isSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000) return Math.floor(time1 / 1000) === Math.floor(time2 / 1000)
} }
export default { export default {
props: { props: {
// 当前选中项的value值 // 当前选中项的value值
value: { value: {
type: [Number, String, Array], type: [Number, String, Array],
default: '' default: ''
}, },
// 菜单项标题 // 菜单项标题
title: { title: {
type: [String, Number], type: [String, Number],
default: '' default: ''
}, },
// 选项数据,如果传入了默认slot,此参数无效 // 选项数据,如果传入了默认slot,此参数无效
options: { options: {
type: Array, type: Array,
default() { default() {
return [] return []
} }
}, },
// 是否禁用此菜单项 // 是否禁用此菜单项
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false
}, },
// 下拉弹窗的高度 // 下拉弹窗的高度
height: { height: {
type: [Number, String], type: [Number, String],
default: 'auto' default: 'auto'
}, },
// 点击遮罩是否可以收起弹窗 // 点击遮罩是否可以收起弹窗
closeOnClickOverlay: { closeOnClickOverlay: {
type: Boolean, type: Boolean,
default: true default: true
} }
} }
} }
<template> <template>
<view class="u-drawdown"> <view class="u-drawdown">
<view <view
class="u-dropdown__menu" class="u-dropdown__menu"
:style="{ :style="{
height: $u.addUnit(height) height: $u.addUnit(height)
}" }"
ref="u-dropdown__menu" ref="u-dropdown__menu"
> >
<view <view
class="u-dropdown__menu__item" class="u-dropdown__menu__item"
v-for="(item, index) in menuList" v-for="(item, index) in menuList"
:key="index" :key="index"
@tap.stop="clickHandler(item, index)" @tap.stop="clickHandler(item, index)"
> >
<view class="u-dropdown__menu__item__content"> <view class="u-dropdown__menu__item__content">
<text <text
class="u-dropdown__menu__item__content__text" class="u-dropdown__menu__item__content__text"
:style="[index === current ? activeStyle : inactiveStyle]" :style="[index === current ? activeStyle : inactiveStyle]"
>{{item.title}}</text> >{{item.title}}</text>
<view <view
class="u-dropdown__menu__item__content__arrow" class="u-dropdown__menu__item__content__arrow"
:class="[index === current && 'u-dropdown__menu__item__content__arrow--rotate']" :class="[index === current && 'u-dropdown__menu__item__content__arrow--rotate']"
> >
<u-icon <u-icon
:name="menuIcon" :name="menuIcon"
:size="$u.addUnit(menuIconSize)" :size="$u.addUnit(menuIconSize)"
></u-icon> ></u-icon>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view class="u-dropdown__content"> <view class="u-dropdown__content">
<slot /> <slot />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import props from './props.js'; import props from './props.js';
/** /**
* Dropdown * Dropdown
* @description * @description
* @tutorial url * @tutorial url
* @property {String} * @property {String}
* @event {Function} * @event {Function}
* @example * @example
*/ */
export default { export default {
name: 'u-dropdown', name: 'u-dropdown',
mixins: [uni.$u.mixin, props], mixins: [uni.$u.mixin, props],
data() { data() {
return { return {
// �˵����� // �˵�����
menuList: [], menuList: [],
current: 0 current: 0
} }
}, },
computed: { computed: {
}, },
created() { created() {
// �������������(u-dropdown-item)��this��������data������������������΢��С��������ѭ�����ö����� // �������������(u-dropdown-item)��this��������data������������������΢��С��������ѭ�����ö�����
this.children = []; this.children = [];
}, },
methods: { methods: {
clickHandler(item, index) { clickHandler(item, index) {
this.children.map(child => { this.children.map(child => {
if(child.title === item.title) { if(child.title === item.title) {
// this.queryRect('u-dropdown__menu').then(size => { // this.queryRect('u-dropdown__menu').then(size => {
child.$emit('click') child.$emit('click')
child.setContentAnimate(child.show ? 0 : 300) child.setContentAnimate(child.show ? 0 : 300)
child.show = !child.show child.show = !child.show
// }) // })
} else { } else {
child.show = false child.show = false
child.setContentAnimate(0) child.setContentAnimate(0)
} }
}) })
}, },
// ��ȡ��ǩ�ijߴ�λ�� // ��ȡ��ǩ�ijߴ�λ��
queryRect(el) { queryRect(el) {
// #ifndef APP-NVUE // #ifndef APP-NVUE
// $uGetRectΪuView�Դ��Ľڵ��ѯ�򻯷���������ĵ����ܣ�https://www.uviewui.com/js/getRect.html // $uGetRectΪuView�Դ��Ľڵ��ѯ�򻯷���������ĵ����ܣ�https://www.uviewui.com/js/getRect.html
// ����ڲ�һ����this.$uGetRect�������Ϊthis.$u.getRect�����߹���һ�£����Ʋ�ͬ // ����ڲ�һ����this.$uGetRect�������Ϊthis.$u.getRect�����߹���һ�£����Ʋ�ͬ
return new Promise(resolve => { return new Promise(resolve => {
this.$uGetRect(`.${el}`).then(size => { this.$uGetRect(`.${el}`).then(size => {
resolve(size) resolve(size)
}) })
}) })
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
// nvue�£�ʹ��domģ���ѯԪ�ظ߶� // nvue�£�ʹ��domģ���ѯԪ�ظ߶�
// ����һ��promise���õ��ô˷�����������ʹ��then�ص� // ����һ��promise���õ��ô˷�����������ʹ��then�ص�
return new Promise(resolve => { return new Promise(resolve => {
dom.getComponentRect(this.$refs[el], res => { dom.getComponentRect(this.$refs[el], res => {
resolve(res.size) resolve(res.size)
}) })
}) })
// #endif // #endif
}, },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
@import '../../libs/css/components.scss'; @import '../../libs/css/components.scss';
.u-dropdown { .u-dropdown {
&__menu { &__menu {
@include flex; @include flex;
&__item { &__item {
flex: 1; flex: 1;
@include flex; @include flex;
justify-content: center; justify-content: center;
&__content { &__content {
@include flex; @include flex;
align-items: center; align-items: center;
} }
} }
} }
} }
</style> </style>
export default { export default {
props: { props: {
// 标题选中时的样式 // 标题选中时的样式
activeStyle: { activeStyle: {
type: [String, Object], type: [String, Object],
...@@ -60,6 +60,6 @@ export default { ...@@ -60,6 +60,6 @@ export default {
menuIconSize: { menuIconSize: {
type: [Number, String], type: [Number, String],
default: 14 default: 14
} }
} }
} }
<template> <template>
<view class="u-drawdown"> <view class="u-drawdown">
<view <view
class="u-dropdown__menu" class="u-dropdown__menu"
:style="{ :style="{
height: $u.addUnit(height) height: $u.addUnit(height)
}" }"
ref="u-dropdown__menu" ref="u-dropdown__menu"
> >
<view <view
class="u-dropdown__menu__item" class="u-dropdown__menu__item"
v-for="(item, index) in menuList" v-for="(item, index) in menuList"
:key="index" :key="index"
@tap.stop="clickHandler(item, index)" @tap.stop="clickHandler(item, index)"
> >
<view class="u-dropdown__menu__item__content"> <view class="u-dropdown__menu__item__content">
<text <text
class="u-dropdown__menu__item__content__text" class="u-dropdown__menu__item__content__text"
:style="[index === current ? activeStyle : inactiveStyle]" :style="[index === current ? activeStyle : inactiveStyle]"
>{{item.title}}</text> >{{item.title}}</text>
<view <view
class="u-dropdown__menu__item__content__arrow" class="u-dropdown__menu__item__content__arrow"
:class="[index === current && 'u-dropdown__menu__item__content__arrow--rotate']" :class="[index === current && 'u-dropdown__menu__item__content__arrow--rotate']"
> >
<u-icon <u-icon
:name="menuIcon" :name="menuIcon"
:size="$u.addUnit(menuIconSize)" :size="$u.addUnit(menuIconSize)"
></u-icon> ></u-icon>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view class="u-dropdown__content"> <view class="u-dropdown__content">
<slot /> <slot />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import props from './props.js'; import props from './props.js';
/** /**
* Dropdown * Dropdown
* @description * @description
* @tutorial url * @tutorial url
* @property {String} * @property {String}
* @event {Function} * @event {Function}
* @example * @example
*/ */
export default { export default {
name: 'u-dropdown', name: 'u-dropdown',
mixins: [uni.$u.mixin, props], mixins: [uni.$u.mixin, props],
data() { data() {
return { return {
// �˵����� // �˵�����
menuList: [], menuList: [],
current: 0 current: 0
} }
}, },
computed: { computed: {
}, },
created() { created() {
// �������������(u-dropdown-item)��this��������data������������������΢��С��������ѭ�����ö����� // �������������(u-dropdown-item)��this��������data������������������΢��С��������ѭ�����ö�����
this.children = []; this.children = [];
}, },
methods: { methods: {
clickHandler(item, index) { clickHandler(item, index) {
this.children.map(child => { this.children.map(child => {
if(child.title === item.title) { if(child.title === item.title) {
// this.queryRect('u-dropdown__menu').then(size => { // this.queryRect('u-dropdown__menu').then(size => {
child.$emit('click') child.$emit('click')
child.setContentAnimate(child.show ? 0 : 300) child.setContentAnimate(child.show ? 0 : 300)
child.show = !child.show child.show = !child.show
// }) // })
} else { } else {
child.show = false child.show = false
child.setContentAnimate(0) child.setContentAnimate(0)
} }
}) })
}, },
// ��ȡ��ǩ�ijߴ�λ�� // ��ȡ��ǩ�ijߴ�λ��
queryRect(el) { queryRect(el) {
// #ifndef APP-NVUE // #ifndef APP-NVUE
// $uGetRectΪuView�Դ��Ľڵ��ѯ�򻯷���������ĵ����ܣ�https://www.uviewui.com/js/getRect.html // $uGetRectΪuView�Դ��Ľڵ��ѯ�򻯷���������ĵ����ܣ�https://www.uviewui.com/js/getRect.html
// ����ڲ�һ����this.$uGetRect�������Ϊthis.$u.getRect�����߹���һ�£����Ʋ�ͬ // ����ڲ�һ����this.$uGetRect�������Ϊthis.$u.getRect�����߹���һ�£����Ʋ�ͬ
return new Promise(resolve => { return new Promise(resolve => {
this.$uGetRect(`.${el}`).then(size => { this.$uGetRect(`.${el}`).then(size => {
resolve(size) resolve(size)
}) })
}) })
// #endif // #endif
// #ifdef APP-NVUE // #ifdef APP-NVUE
// nvue�£�ʹ��domģ���ѯԪ�ظ߶� // nvue�£�ʹ��domģ���ѯԪ�ظ߶�
// ����һ��promise���õ��ô˷�����������ʹ��then�ص� // ����һ��promise���õ��ô˷�����������ʹ��then�ص�
return new Promise(resolve => { return new Promise(resolve => {
dom.getComponentRect(this.$refs[el], res => { dom.getComponentRect(this.$refs[el], res => {
resolve(res.size) resolve(res.size)
}) })
}) })
// #endif // #endif
}, },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
@import '../../libs/css/components.scss'; @import '../../libs/css/components.scss';
.u-dropdown { .u-dropdown {
&__menu { &__menu {
@include flex; @include flex;
&__item { &__item {
flex: 1; flex: 1;
@include flex; @include flex;
justify-content: center; justify-content: center;
&__content { &__content {
@include flex; @include flex;
align-items: center; align-items: center;
} }
} }
} }
} }
</style> </style>
export default { export default {
props: { props: {
// 图片地址 // 图片地址
src: { src: {
type: String, type: String,
default: uni.$u.props.image.src default: uni.$u.props.image.src
}, },
// 裁剪模式 // 裁剪模式
mode: { mode: {
type: String, type: String,
default: uni.$u.props.image.mode default: uni.$u.props.image.mode
}, },
// 宽度,单位任意 // 宽度,单位任意
width: { width: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.image.width default: uni.$u.props.image.width
}, },
// 高度,单位任意 // 高度,单位任意
height: { height: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.image.height default: uni.$u.props.image.height
}, },
// 图片形状,circle-圆形,square-方形 // 图片形状,circle-圆形,square-方形
shape: { shape: {
type: String, type: String,
default: uni.$u.props.image.shape default: uni.$u.props.image.shape
}, },
// 圆角,单位任意 // 圆角,单位任意
radius: { radius: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.image.radius default: uni.$u.props.image.radius
}, },
// 是否懒加载,微信小程序、App、百度小程序、字节跳动小程序 // 是否懒加载,微信小程序、App、百度小程序、字节跳动小程序
lazyLoad: { lazyLoad: {
type: Boolean, type: Boolean,
default: uni.$u.props.image.lazyLoad default: uni.$u.props.image.lazyLoad
}, },
// 开启长按图片显示识别微信小程序码菜单 // 开启长按图片显示识别微信小程序码菜单
showMenuByLongpress: { showMenuByLongpress: {
type: Boolean, type: Boolean,
default: uni.$u.props.image.showMenuByLongpress default: uni.$u.props.image.showMenuByLongpress
}, },
// 加载中的图标,或者小图片 // 加载中的图标,或者小图片
loadingIcon: { loadingIcon: {
type: String, type: String,
default: uni.$u.props.image.loadingIcon default: uni.$u.props.image.loadingIcon
}, },
// 加载失败的图标,或者小图片 // 加载失败的图标,或者小图片
errorIcon: { errorIcon: {
type: String, type: String,
default: uni.$u.props.image.errorIcon default: uni.$u.props.image.errorIcon
}, },
// 是否显示加载中的图标或者自定义的slot // 是否显示加载中的图标或者自定义的slot
showLoading: { showLoading: {
type: Boolean, type: Boolean,
default: uni.$u.props.image.showLoading default: uni.$u.props.image.showLoading
}, },
// 是否显示加载错误的图标或者自定义的slot // 是否显示加载错误的图标或者自定义的slot
showError: { showError: {
type: Boolean, type: Boolean,
default: uni.$u.props.image.showError default: uni.$u.props.image.showError
}, },
// 是否需要淡入效果 // 是否需要淡入效果
fade: { fade: {
type: Boolean, type: Boolean,
default: uni.$u.props.image.fade default: uni.$u.props.image.fade
}, },
// 只支持网络资源,只对微信小程序有效 // 只支持网络资源,只对微信小程序有效
webp: { webp: {
type: Boolean, type: Boolean,
default: uni.$u.props.image.webp default: uni.$u.props.image.webp
}, },
// 过渡时间,单位ms // 过渡时间,单位ms
duration: { duration: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.image.duration default: uni.$u.props.image.duration
}, },
// 背景颜色,用于深色页面加载图片时,为了和背景色融合 // 背景颜色,用于深色页面加载图片时,为了和背景色融合
bgColor: { bgColor: {
type: String, type: String,
default: uni.$u.props.image.bgColor default: uni.$u.props.image.bgColor
} }
} }
} }
export default { export default {
props: { props: {
// 是否显示组件 // 是否显示组件
show: { show: {
type: Boolean, type: Boolean,
default: uni.$u.props.loadingIcon.show default: uni.$u.props.loadingIcon.show
}, },
// 颜色 // 颜色
color: { color: {
type: String, type: String,
default: uni.$u.props.loadingIcon.color default: uni.$u.props.loadingIcon.color
}, },
// 提示文字颜色 // 提示文字颜色
textColor: { textColor: {
type: String, type: String,
default: uni.$u.props.loadingIcon.textColor default: uni.$u.props.loadingIcon.textColor
}, },
// 文字和图标是否垂直排列 // 文字和图标是否垂直排列
vertical: { vertical: {
type: Boolean, type: Boolean,
default: uni.$u.props.loadingIcon.vertical default: uni.$u.props.loadingIcon.vertical
}, },
// 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形 // 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形
mode: { mode: {
type: String, type: String,
default: uni.$u.props.loadingIcon.mode default: uni.$u.props.loadingIcon.mode
}, },
// 图标大小,单位默认px // 图标大小,单位默认px
size: { size: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.loadingIcon.size default: uni.$u.props.loadingIcon.size
}, },
// 文字大小 // 文字大小
textSize: { textSize: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.loadingIcon.textSize default: uni.$u.props.loadingIcon.textSize
}, },
// 文字内容 // 文字内容
text: { text: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.loadingIcon.text default: uni.$u.props.loadingIcon.text
}, },
// 动画模式 // 动画模式
timingFunction: { timingFunction: {
type: String, type: String,
default: uni.$u.props.loadingIcon.timingFunction default: uni.$u.props.loadingIcon.timingFunction
}, },
// 动画执行周期时间 // 动画执行周期时间
duration: { duration: {
type: [String, Number], type: [String, Number],
default: uni.$u.props.loadingIcon.duration default: uni.$u.props.loadingIcon.duration
}, },
// mode=circle时的暗边颜色 // mode=circle时的暗边颜色
inactiveColor: { inactiveColor: {
type: String, type: String,
default: uni.$u.props.loadingIcon.inactiveColor default: uni.$u.props.loadingIcon.inactiveColor
} }
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论