Skip to content

练习案例

商品首页

展示商品

ts
# 设置行内样式 超过两行 显示 ...
    设置高度		80rpx  
    设置文本的行数	  line-clamp:2
	文本溢出...		ellipsis
    设置伸缩布局	   flex
# 回到顶部的样式
	使用固定定位
    使用wx:if或wx:show控制隐藏
    监听页面滚动回调钩子
    	默认参数event是滚动的位置
    	定义响应式数据,使用if判断
	点击图标滚动位置
    	使用全局对象的方法 pageScrollTo({})

首页样式

/pages/index/index.wxss

css
.home{
    width: 100%;
    height: 100%;
}
.home .swiper{
    width: 750rpx;
    height: 350rpx;
}
.home .swiper .image{
    width: 750rpx;
    height: 350rpx;
}
.home .category{
    display: flex;
    flex-wrap: wrap;
}
.home .category .category-item{
    width: 146rpx;
    width: 146rpx;
    display: flex;
    flex-direction:column;
    justify-content: center;
    align-items: center;
    background-color: #b7d9eb;
    border: 2rpx solid #ccc;
}
.home .category .category-item .category-image{
    width: 80rpx;
    height: 80rpx;
}
.home .category .category-item .category-title{
    font-size: 30rpx;
}

.home .good{
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around; /* 两端的间距是中间的一半 */
}
.home .good .good-item{
    width: 320rpx;
    margin-top: 20rpx;
    border: solid 2rpx #ccc;
}
.home .good .good-item .good-item-img{
    width: 320rpx;
    height: 320rpx;
}
.home .good .good-item .good-item-title{
    font-size: 30rpx;
    display: -webkit-box;       /* 创建弹性盒子 */
    -webkit-box-orient: vertical; /* 设置方向为垂直 */
    overflow: hidden;           /* 隐藏超出的内容 */
    text-overflow: ellipsis;    /* 超出部分用省略号 */
    -webkit-line-clamp: 2;      /* 限制显示的行数 */
    word-wrap: break-word;      /* 单词折行 */
}
/* 固定定位到右下角 */
.home .totop{
    position: fixed; /* 固定定位 */
    right: 30rpx;
    bottom: 100rpx;
}
.home .totop .totop-img{
    width: 80rpx;
    height: 80rpx;
}

首页静态

/pages/index/index.wxml

xml
<view class="home">
    <!-- 轮播图 -->
    <swiper class="swiper" 	indicator-dots 	indicator-color="#dbdbdb" 	indicator-active-color="#d81e06" autoplay circular>
        <swiper-item>
            <image class="image" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118150656.png" mode="aspectFill"/>
        </swiper-item>
        <swiper-item>
            <image class="image" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118150656.png" mode="aspectFill"/>
        </swiper-item>
        <swiper-item>
            <image class="image" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118150656.png" mode="aspectFill"/>
        </swiper-item>
    </swiper>
    <!-- 分类 -->
    <view class="category">
        <view class="category-item">
            <image class="category-image" src="/static/category/a-duankouduomeiti.png" mode="aspectFill"/>
            <text class="category-title">多媒体</text>
        </view>
        <view class="category-item">
            <image class="category-image" src="/static/category/a-huandengpianpptyanshiduomeiti.png" mode="aspectFill"/>
            <text class="category-title">PPT</text>
        </view>
        <view class="category-item">
            <image class="category-image" src="/static/category/a-jiangtaijiaocheng.png" mode="aspectFill"/>
            <text class="category-title">讲台</text>
        </view>    
        <view class="category-item">
            <image class="category-image" src="/static/category/a-tupianzhaopian.png" mode="aspectFill"/>
            <text class="category-title">照片</text>
        </view>     
        <view class="category-item">
            <image class="category-image" src="/static/category/a-zhaoxiangjizhaopianpaisheduomeiti.png" mode="aspectFill"/>
            <text class="category-title">视频</text>
        </view>    
        <view class="category-item">
            <image class="category-image" src="/static/category/a-duankouduomeiti.png" mode="aspectFill"/>
            <text class="category-title">多媒体</text>
        </view>     
        <view class="category-item">
            <image class="category-image" src="/static/category/a-huandengpianpptyanshiduomeiti.png" mode="aspectFill"/>
            <text class="category-title">PPT</text>
        </view>
        <view class="category-item">
            <image class="category-image" src="/static/category/a-jiangtaijiaocheng.png" mode="aspectFill"/>
            <text class="category-title">讲台</text>
        </view>
        <view class="category-item">
            <image class="category-image" src="/static/category/a-tupianzhaopian.png" mode="aspectFill"/>
            <text class="category-title">照片</text>
        </view>    
        <view class="category-item">
            <image class="category-image" src="/static/category/a-zhaoxiangjizhaopianpaisheduomeiti.png" mode="aspectFill"/>
            <text class="category-title">视频</text>
        </view>
    </view>
    <!-- 商品列表 -->
    <view class="good">
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118104045.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118155049.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118104045.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118155049.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118104045.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118155049.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118104045.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
        <view class="good-item">
            <image class="good-item-img" src="https://2216847528.oss-cn-beijing.aliyuncs.com/asset/20241118155049.png" mode="aspectFill"/>
            <text class="good-item-title" >樱井雪乃,用日语写作是さくらい ゆきの,罗马音表示为Yukino Sakurai。这位角色以其独特的魅力在动漫界吸引了不少粉丝,她的配音员是柚木凉香,为我们带来生动的</text>
        </view>
    </view>
    <!-- 回到顶部 -->
    <view class="totop">
        <image wx:if="{{showtopBtn}}" bind:tap="toTop" class="totop-img" src="/static/category/toTop.png" mode="aspectFill"/>
    </view>
</view>

首页数据

/pages/index/index.js

js
//通过Page方法创建页面   App->Page
Page({
    //页面数据
    data: {
        name: '结城sakuna',
        deg:0,
        showtopBtn:false
    },
    //编程式导航按钮回调
    goDetail(){
        //编程式导航页面跳转
        //navigateTo:A->B,但是A页面不会销毁(不能跳转到tabbar页面)
        //redirectTo 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
        wx.redirectTo({
          url: '/pages/detail/detail?a=1&b=2',
        })
    },
    // 监听页面滚动
    onPageScroll(event){
        // 判断
        if(event.scrollTop >= 300){
            this.setData({
                showtopBtn:true
            })
        }else{
            this.setData({
                showtopBtn:false
            })
        }
    },
    // 回到顶部
    toTop(){
        wx.pageScrollTo({
            scrollTop:0,
            duration:400
        })
    }
})

Tabbar

/app.json

json
{
    "pages": [
        "pages/index/index",
        "pages/user/user",
        "pages/shopcart/shopcart"
    ],
    "window": {
        "navigationBarBackgroundColor": "#2980B9",
        "navigationBarTextStyle": "black",
        "navigationBarTitleText": "结城sakana"
    },
    "tabBar": {
        "list": [
            {
                "pagePath": "pages/index/index",
                "text": "首页",
                "iconPath": "/static/tabbar/shouye1.png",
                "selectedIconPath": "/static/tabbar/shouye.png"
            },
            {
                "pagePath": "pages/shopcart/shopcart",
                "text": "购物车",
                "iconPath": "/static/tabbar/shopcart1.png",
                "selectedIconPath": "/static/tabbar/shopcart.png"
            },
            {
                "pagePath": "pages/user/user",
                "text": "个人中心",
                "iconPath": "/static/tabbar/user1.png",
                "selectedIconPath": "/static/tabbar/user.png"
            }
        ],
        "color": "#2980B9",
        "selectedColor": "d81e06",
        "backgroundColor": "#ccc"
    }
}

文字超出隐藏

css
.good .good-item .good-item-title{
    font-size: 30rpx;
    display: -webkit-box;       /* 创建弹性盒子 */
    -webkit-box-orient: vertical; /* 设置方向为垂直 */
    overflow: hidden;           /* 隐藏超出的内容 */
    text-overflow: ellipsis;    /* 超出部分用省略号 */
    -webkit-line-clamp: 2;      /* 限制显示的行数 */
    word-wrap: break-word;      /* 单词折行 */
}

回到顶部按钮

css
# 定位布局
# 监听页面滚动
js
// 回到顶部
toTop(){
    wx.pageScrollTo({
        scrollTop:0,
        duration:400
    })
}

uni案例-萌宠

底部安全区环境变量

ts
padding-bottom:env(safe-area-inset-bottom)

萌宠案例

pets.vue

vue
<template>
    <view class="container">
        <!-- 菜单 -->
        <view class="menu">
            <uni-segmented-control
                :current="current"
                :values="values"
                @clickItem="onClickItem"
                styleType="button"
                activeColor="#2B9939"></uni-segmented-control>
        </view>
        <!-- 内容 -->
        <view class="layout">
            <view class="box" v-for="(item, index) in pets" :key="item._id">
                <view class="pic">
                    <image
                        lazy-load
                        :src="item.url"
                        mode="widthFix"
                        @click="onPreview(index)"></image>
                </view>
                <view class="text">{{ item.content }}</view>
                <view class="author">—— {{ item.author }}</view>
            </view>
        </view>
        <!-- 刷新和回到顶部 -->
        <view class="float">
            <view class="item" @click="onRefresh">
                <uni-icons
                    type="refreshempty"
                    size="26"
                    color="#888"></uni-icons>
            </view>
            <view class="item" @click="onTop">
                <uni-icons type="arrow-up" size="26" color="#888"></uni-icons>
            </view>
        </view>
        <!-- 加载更多 -->
        <view class="loadMore">
            <uni-load-more :status="status" iconType="auto"></uni-load-more>
        </view>
    </view>
</template>

<script setup>
import { computed, ref } from "vue";
import { onReachBottom, onPullDownRefresh, onReady } from "@dcloudio/uni-app";
// 定义数据数组
const pets = ref([]);
// 当前分类
const current = ref(0);
// 当前状态
const status = ref("loading");

// 分类数据格式
const classify = [
    { key: "all", value: "全部" },
    { key: "dog", value: "狗狗" },
    { key: "cat", value: "猫猫" },
];
// 通过计算属性 算出分段器的数据格式
const values = computed(() => classify.map((item) => item.value));

//点击菜单回调
const onClickItem = (e) => {
    // 设置当前页面的索引
    current.value = e.currentIndex;
    // 清空数据
    pets.value = [];
    // 重新发送请求
    network();
};
//点击预览
const onPreview = function (index) {
    // 获取图片url数组
    let urls = pets.value.map((item) => item.url);
    // 触发预览图片
    uni.previewImage({
        current: index,
        urls,
    });
};

//点击刷新
const onRefresh = function () {
    // 开始下拉刷新
    console.log("点击刷新执行了");
    uni.startPullDownRefresh();
};
//返回顶部
const onTop = () => {
    // 滚动API
    uni.pageScrollTo({
        scrollTop: 0,
        duration: 100,
    });
};

//发送网络请求
function network() {
    // 导航栏加载样式
    // uni.showNavigationBarLoading();
    status.value = "loading";
    // 发送网络请求
    uni.request({
        url: "https://tea.qingnian8.com/tools/petShow",
        data: {
            size: 5,
            type: classify[current.value].key,
        },
        header: {
            "access-key": "sakuna7758521",
        },
    })
        .then((res) => {
            if (res.data.errCode === 0) {
                pets.value = [...pets.value, ...res.data.data];
                console.log(pets.value);
            } else if (res.data.errCode === 400) {
                uni.showToast({
                    title: res.data.errMsg,
                    icon: "fail",
                });
            }
        })
        .catch((err) => {
            uni.showToast({
                title: "请求有误,请重新刷新",
                icon: "none",
            });
        })
        .finally(() => {
            // 隐藏导航栏加载样式
            // uni.hideNavigationBarLoading();
            // 停止刷新
            uni.stopPullDownRefresh();
            status.value = "more";
        });
}

// 触底加载生命周期
onReachBottom(() => {
    // 发送网络请求
    network();
});

// 下拉刷新生命周期
onPullDownRefresh(() => {
    // 清空数据
    pets.value = [];
    // 设置当前分类为0
    current.value = 0;
    // 发送网络请求
    network();
});

network();
// 发送网络请求 在setup阶段就发送网络请求
</script>

<style lang="scss" scoped>
.container {
    .menu {
        padding: 50rpx 50rpx 0;
    }

    .layout {
        padding: 50rpx;
        .box {
            margin-bottom: 60rpx;
            box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
            border-radius: 15rpx;
            overflow: hidden;
            .pic {
                image {
                    width: 100%;
                }
            }
            .text {
                padding: 30rpx;
                color: #333;
                font-size: 36rpx;
            }
            .author {
                padding: 0 30rpx 30rpx;
                text-align: right;
                color: #888;
                font-size: 28rpx;
            }
        }
    }

    .loadMore {
        padding-bottom: calc(env(safe-area-inset-bottom) + 50rpx);
    }

    .float {
        position: fixed;
        right: 30rpx;
        bottom: 80rpx;
        padding-bottom: env(safe-area-inset-bottom);
        .item {
            width: 90rpx;
            height: 90rpx;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 50%;
            margin-bottom: 20rpx;
            display: flex;
            align-items: center;
            justify-content: center;
            border: 1px solid #eee;
        }
    }
}
</style>

pages.json

json
{
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			"path" : "pages/pets/pets",
			"style" : 
			{
				"navigationBarTitleText" : "pets",
				"enablePullDownRefresh": true
			}
		},
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "uni-app"
			}
		},
		{
			"path" : "pages/device/device",
			"style" : 
			{
				"navigationBarTitleText" : ""
			}
		}
	],
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	},
	"uniIdRouter": {}
}