通知组件
代码封装
<template>
<!-- 通知 -->
<view class="notice">
<image
class="notice-icon"
src="@/assets/images/tz.png"
mode="aspectFit"
/>
<view class="notice-ticker">
<view
class="ticker-list"
:class="{ 'is-no-transition': noTransition }"
:style="{ transform: `translateY(-${current * 40}rpx)` }"
>
<view
v-for="(item, index) in tickerList"
:key="index"
class="ticker-item"
@tap="onItemClick(item)"
>
<text class="ticker-text">{{ item.title }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, watch, onMounted, onUnmounted } from "vue";
const props = defineProps({
notices: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(["onChange"]);
/* 点击某条通知 */
const onItemClick = (item) => {
console.log(item);
emit("onChange", item);
};
const tickerList = computed(() => {
if (!props.notices.length) return [];
return [...props.notices, props.notices[0]];
});
const current = ref(0);
const noTransition = ref(false);
const DELAY = 4000;
let timer = null;
const tick = () => {
if (current.value >= tickerList.value.length - 1) {
noTransition.value = true;
current.value = 0;
setTimeout(() => {
noTransition.value = false;
}, 50);
} else {
current.value++;
}
};
const start = () => {
stop();
if (props.notices.length > 1) {
timer = setInterval(tick, DELAY);
}
};
const stop = () => {
if (timer) {
clearInterval(timer);
timer = null;
}
};
watch(() => props.notices, start);
onMounted(start);
onUnmounted(stop);
</script>
<style lang="scss" scoped>
.notice {
display: flex;
align-items: center;
gap: 6rpx;
height: 60rpx;
padding: 0 16rpx;
box-sizing: border-box;
background: #f7faff;
border-radius: 12rpx;
.notice-icon {
width: 48rpx;
height: 48rpx;
flex-shrink: 0;
}
.notice-ticker {
flex: 1;
min-width: 0;
height: 40rpx;
padding-left: 6rpx;
overflow: hidden;
.ticker-list {
display: flex;
flex-direction: column;
transition: transform 0.4s ease;
&.is-no-transition {
transition: none;
}
.ticker-item {
height: 40rpx;
line-height: 40rpx;
.ticker-text {
display: block;
font-size: 22rpx;
color: rgba(0, 104, 254, 0.9);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}
</style>
使用
<!-- 通知 -->
<notice :notices="noticeList" />
/* 通知 */
const noticeList = [
{ id: 1, title: "沪锡大涨激活工业金属涨价逻辑,这背后是全球增长预期" },
{ id: 2, title: "BTC 站上 68000 美元关口,市场看多情绪持续升温撒旦飞洒飞洒发生发士大夫撒飞洒发生" },
{ id: 3, title: "ETH 生态活跃度持续提升,链上交易量创近期新高" },
];
轮播图组件
代码封装
<template>
<!-- 轮播图 -->
<view class="banner-wrap">
<uni-swiper-dot
:info="banners"
:current="current"
mode="round"
field="content"
:dotsStyles="dotStyles"
@clickItem="clickItem"
>
<swiper
class="banner-swiper"
:current="current"
@change="change"
circular
autoplay
:interval="8000"
:duration="300"
>
<swiper-item v-for="(item, index) in banners" :key="index">
<image class="banner-img" :src="item.src" mode="scaleToFill" @click="handleClick(item)" />
</swiper-item>
</swiper>
</uni-swiper-dot>
</view>
</template>
<script setup>
import { ref } from "vue";
const props = defineProps({
banners: {
type: Array,
default: () => [],
},
});
const current = ref(0);
const emit = defineEmits(["click"]);
const dotStyles = {
backgroundColor: "#0068FE",
selectedBackgroundColor: "#0068FE",
border: "none",
selectedBorder: "none",
};
const change = (e) => {
current.value = e.detail.current;
};
const clickItem = (e) => {
current.value = e;
};
const handleClick = (item) => {
if (!item.type) return;
if (item.type === "page") {
goPath(item.url);
} else if (item.type === "link") {
const title = item.title || "";
goPath(
`/pages/webview/webview?url=${encodeURIComponent(item.url)}&title=${encodeURIComponent(title)}`
);
}
};
const goPath = (path) => {
uni.navigateTo({
url: path,
fail: () => uni.switchTab({ url: path }),
});
};
</script>
<style lang="scss" scoped>
.banner-wrap {
padding: 24rpx 0 0;
.banner-swiper {
width: 100%;
height: 176rpx;
border-radius: 16rpx;
overflow: hidden;
}
.banner-img {
width: 100%;
height: 176rpx;
display: block;
}
}
</style>
使用
<banner :banners="banners" />
/* 轮播图 */
const banners = [
{ src: "/assets/images/lbt.png", type: "page", url: "/pages/asset/asset" },
{ src: "/assets/images/lbt.png", type: "link", url: "https://www.xxxx.com" },
{ src: "/assets/images/lbt.png" },
];