diff --git a/package.json b/package.json
index 8a43ddfe0..27236e84c 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
"dependencies": {
"@babel/runtime": "7.x",
"@vant/icons": "1.3.0",
- "@vant/use": "^0.0.1",
+ "@vant/use": "^0.0.2",
"vue-lazyload": "1.2.3"
},
"peerDependencies": {
diff --git a/src/coupon-list/index.js b/src/coupon-list/index.js
index c909246b8..5a6d09207 100644
--- a/src/coupon-list/index.js
+++ b/src/coupon-list/index.js
@@ -1,6 +1,12 @@
+import { watch, computed, nextTick, onMounted, reactive } from 'vue';
+
// Utils
import { createNamespace } from '../utils';
+// Composition
+import { useWindowSize } from '@vant/use';
+import { useRefs } from '../composition/use-refs';
+
// Components
import Tab from '../tab';
import Tabs from '../tabs';
@@ -65,178 +71,168 @@ export default createComponent({
emits: ['change', 'exchange', 'update:code'],
- data() {
- return {
+ setup(props, { emit }) {
+ const [couponRefs, setCouponRefs] = useRefs();
+
+ const state = reactive({
tab: 0,
- winHeight: window.innerHeight,
- currentCode: this.code || '',
- };
- },
+ code: props.code || '',
+ });
- computed: {
- buttonDisabled() {
- return (
- !this.exchangeButtonLoading &&
- (this.exchangeButtonDisabled ||
- !this.currentCode ||
- this.currentCode.length < this.exchangeMinLength)
- );
- },
+ const { height: windowHeight } = useWindowSize();
- listStyle() {
- return {
- height: this.winHeight - (this.showExchangeBar ? 140 : 94) + 'px',
- };
- },
- },
+ const buttonDisabled = computed(
+ () =>
+ !props.exchangeButtonLoading &&
+ (props.exchangeButtonDisabled ||
+ !state.code ||
+ state.code.length < props.exchangeMinLength)
+ );
- watch: {
- code(code) {
- this.currentCode = code;
- },
+ const listStyle = computed(() => ({
+ height: windowHeight.value - (props.showExchangeBar ? 140 : 94) + 'px',
+ }));
- currentCode(code) {
- this.$emit('update:code', code);
- },
-
- displayedCouponIndex: 'scrollToShowCoupon',
- },
-
- mounted() {
- this.scrollToShowCoupon(this.displayedCouponIndex);
- },
-
- methods: {
- onClickExchangeButton() {
- this.$emit('exchange', this.currentCode);
+ const onExchange = () => {
+ emit('exchange', state.code);
// auto clear currentCode when not use vModel
- if (!this.code) {
- this.currentCode = '';
+ if (!props.code) {
+ state.code = '';
}
- },
+ };
- // scroll to show specific coupon
- scrollToShowCoupon(index) {
- if (index === -1) {
- return;
- }
-
- this.$nextTick(() => {
- const { card, list } = this.$refs;
-
- /* istanbul ignore next */
- if (list && card && card[index]) {
- list.scrollTop = card[index].$el.offsetTop - 100;
+ const scrollToCoupon = (index) => {
+ nextTick(() => {
+ if (couponRefs.value[index]) {
+ couponRefs.value[index].scrollIntoView();
}
});
- },
+ };
- genEmpty() {
- return (
-
-

-
{t('empty')}
-
- );
- },
-
- genExchangeButton() {
- return (
-
- );
- },
- },
-
- render() {
- const { coupons, disabledCoupons } = this;
-
- const count = this.showCount ? ` (${coupons.length})` : '';
- const title = (this.enabledTitle || t('enable')) + count;
-
- const disabledCount = this.showCount ? ` (${disabledCoupons.length})` : '';
- const disabledTitle = (this.disabledTitle || t('disabled')) + disabledCount;
-
- const ExchangeBar = this.showExchangeBar && (
-
-
- {this.genExchangeButton()}
+ const renderEmpty = () => (
+
+

+
{t('empty')}
);
- const onChange = (index) => () => this.$emit('change', index);
-
- const CouponTab = (
-
-
- {coupons.map((coupon, index) => (
-
{
+ if (props.showExchangeBar) {
+ return (
+
+
- ))}
- {!coupons.length && this.genEmpty()}
-
-
+
+
+ );
+ }
+ };
+
+ const renderCouponTab = () => {
+ const { coupons } = props;
+ const count = props.showCount ? ` (${coupons.length})` : '';
+ const title = (props.enabledTitle || t('enable')) + count;
+
+ return (
+
+
+ {coupons.map((coupon, index) => (
+ emit('change', index)}
+ />
+ ))}
+ {!coupons.length && renderEmpty()}
+
+
+ );
+ };
+
+ const renderDisabledTab = () => {
+ const { disabledCoupons } = props;
+ const count = props.showCount ? ` (${disabledCoupons.length})` : '';
+ const title = (props.disabledTitle || t('disabled')) + count;
+
+ return (
+
+
+ {disabledCoupons.map((coupon) => (
+
+ ))}
+ {!disabledCoupons.length && renderEmpty()}
+
+
+ );
+ };
+
+ watch(
+ () => props.code,
+ (value) => {
+ state.code = value;
+ }
);
- const DisabledCouponTab = (
-
-
- {disabledCoupons.map((coupon) => (
-
- ))}
- {!disabledCoupons.length && this.genEmpty()}
-
-
+ watch(
+ () => state.code,
+ (value) => {
+ emit('update:code', value);
+ }
);
- return (
+ watch(() => props.displayedCouponIndex, scrollToCoupon);
+
+ onMounted(() => {
+ scrollToCoupon(props.displayedCouponIndex);
+ });
+
+ return () => (
- {ExchangeBar}
-
- {CouponTab}
- {DisabledCouponTab}
+ {renderExchangeBar()}
+
+ {renderCouponTab()}
+ {renderDisabledTab()}
diff --git a/yarn.lock b/yarn.lock
index 955f996de..2f80426f0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2156,10 +2156,10 @@
resolved "https://registry.yarnpkg.com/@vant/touch-emulator/-/touch-emulator-1.2.0.tgz#486300b23e57db9ce9231a04e0a0c621c68692d8"
integrity sha512-sJ97zU85zOq51qoi7+CpBEcOyH3CitjP1KC7/GQwqaurUJni+EP7/F9n0HMnAh8GXMjgtgDBNJ5z48x+coNKYQ==
-"@vant/use@^0.0.1":
- version "0.0.1"
- resolved "https://registry.npmjs.org/@vant/use/-/use-0.0.1.tgz#66ed5dd186e54a6ec1b48604bfd8c0f466d9d568"
- integrity sha512-AQrKFoiC4sZqRI6mx4a4iHekcpcvNYcZDo/0/WTMejtjKygaKMlImmOR36JWYinhvQwjO6GnAgQDvuO/hNwCPA==
+"@vant/use@^0.0.2":
+ version "0.0.2"
+ resolved "https://registry.npmjs.org/@vant/use/-/use-0.0.2.tgz#9ea72642e0d6ef664f19e80b73fdb59b9f403d21"
+ integrity sha512-kPgqwBMKaeKPQ/LZjjVDHKxo2Thi4w5M186+Yg4jATW7qCcfd0CujDmqlETfFjBCbw40C1HVu/kmhXE0cQPPUg==
"@vue/babel-helper-vue-transform-on@^1.0.0-rc.2":
version "1.0.0-rc.2"