前言
- 完成项目需掌握技术
- Javascript
- Vue
- 微信小程序
- sass
- 接口文档
- https://github.com/lhl-cpu/uni-app-
uni-app简介
- uni-app 是一个使用 Vue.js语法来开发所有前端应用的框架,称为全端开发框架
配置环境
脚手架搭建项目
- 全局安装
- npm install -g @vue/cli
- 创建项目
- vue create -p dcloudio/uni-preset-vue my-project
- 启动项目
- npm run dev:mp-weixin
- 微信小程序开发工具导入项目
- 全局安装
项目目录
│ App.vue 应用配置,用来配置App全局样式以及监听
│ main.js Vue初始化入口文件
│ manifest.json 配置应用名称、appid、logo、版本等打包信息
│ pages.json 配置页面路由、导航条、选项卡等页面类信息
│ uni.scss 内置的sass变量,可以直接使用
│
|─pages
│ └─index
│ index.vue 页面组件
│
└─static 静态资源
logo.png样式和sass
- 支持小程序的rpx 和 h5的vw、vh
- 内置有sass的配置了,只需要 安装对应的依赖即可 “ npm install sass-loader node-sass ”
- vue组件中,在 style 标签上 加入 属性 “
模块基本功能
搭建首页子页面
- 首页模块分为 4个部分,分别是 推荐、分类、最新、专辑
- 新建自定义组件来代替 上述的4个页面
- home-recommend
- home-category
- home-new
- home-album
分段器使用
- 分段器指的是 uni-ui 中的一个组件,其实就是我们俗称的 标签页,tab栏
- https://ext.dcloud.net.cn/plugin?id=54
<template>
<view class="home_tab">
<view class="home_tab_title">
<view class="title_inner">
<uni-segmented-control
:current="current"
:values="items.map((v) => v.title)"
@clickItem="onClickItem"
style-type="text"
active-color="#e63a7d"
></uni-segmented-control>
</view>
<view class="iconfont iconsearch"></view>
</view>
<view class="home_tab_content">
<view v-if="current === 0">
<recommend></recommend>
</view>
<view v-if="current === 1">
<category></category>
</view>
<view v-if="current === 2">
<anew></anew>
</view>
<view v-if="current === 3">
<album></album>
</view>
</view>
</view>
</template>
<script>
import recommend from "./home-recommend/index.vue";
import category from "./home-category/index.vue";
import anew from "./home-new/index.vue";
import album from "./home-album/index.vue";
//引入
import uniSegmentedControl from "../../../node_modules/@dcloudio/uni-ui/lib/uni-segmented-control/uni-segmented-control.vue";
export default {
components: {
recommend,
category,
anew,
album,
uniSegmentedControl,
},
data() {
return {
items: [
{ title: "推荐" },
{ title: "分类" },
{ title: "最新" },
{ title: "专辑" },
],
current: 0,
};
},
methods: {
onClickItem(e) {
if (this.current !== e.currentIndex) {
this.current = e.currentIndex;
}
},
}
};
</script>
<style lang="scss">
.home_tab_title {
position: relative;
.title_inner {
width: 70%;
margin: 0 auto;
}
.iconsearch {
position: absolute;
top: 45%;
transform: translateY(-50%);
right: 6%;
}
}
.home_tab_content {
}
</style>封装自己的异步请求
为什么要封装
- 原生的请求不支持 promise
- uni-api 的请求不能够方便的添加 请求中 效果
- uni-api 的请求返回值是个数组,不方便
封装思路
- 基于原生的promise来封装
- 挂载到Vue的原型上
- 通过 this.request 的方式来使用
export default (params) => {
uni.showLoading({
title: "加载中",
});
return new Promise((resolve, reject) => {
wx.request({
...params,
success(res) {
resolve(res.data);
},
fail(err) {
resolve(err);
},
complete() {
uni.hideLoading();
},
});
});
};首页推荐模块
数据动态渲染
moment.js 的使用
基于scroll-view的分页加载
绑定滚动条触底事件 scrolltolower
实现分页逻辑
<template>
<scroll-view
@scrolltolower="handleToLower"
class="recommend_view"
scroll-y
v-if="recommends.length"
>
<!-- 推荐开始 -->
<view class="recommend_wrap">
<navigator
class="recommend_item"
v-for="(item, index) in recommends"
:key="index"
:url="`/pages/ablum/index?id=${item.target}`"
>
<image mode="widthFix" :src="item.thumb"></image>
</navigator>
</view>
<!-- 推荐结束 -->
<!-- 月份开始 -->
<view class="moneths_wrap">
<view class="moneths_title">
<view class="moneths_title_info">
<view class="moneths_info">
<text>{{ monthes.DD }}</text>
/{{ monthes.MM }}月
</view>
<view class="moneths_text">{{ monthes.title }}</view>
</view>
<view class="moneths_title_more">更多 ></view>
</view>
<view class="moneths_content">
<view
class="moneths_item"
v-for="(item, index) in monthes.items"
:key="index"
>
<godetail :list="monthes.items" :index="index">
<image
mode="aspectFill"
:src="item.thumb + item.rule.replace('$<Height>', 360)"
></image>
</godetail>
</view>
</view>
</view>
<!-- 月份结束 -->
<!-- 热门开始 -->
<view class="hots_wrap">
<view class="hots_title">
<text>热门</text>
</view>
<view class="hots_content">
<view class="hot_item" v-for="(item, index) in hots" :key="index">
<godetail :list="hots" :index="index">
<image mode="widthFix" :src="item.thumb"></image>
</godetail>
</view>
</view>
</view>
<!-- 热门结束 -->
</scroll-view>
</template>
<script>
import moment from "moment";
import godetail from "../../../components/goDetail";
export default {
data() {
return {
recommends: [],
monthes: {},
hots: [],
params: {
limit: 30,
order: "hot",
skip: 0,
},
havemore: true,
};
},
components: {
godetail,
},
mounted() {
uni.setNavigationBarTitle({
title: "推荐",
});
this.getList();
},
methods: {
getList() {
this.request({
url: "http://157.122.54.189:9088/image/v3/homepage/vertical",
data: this.params,
}).then((result) => {
if (result.res.vertical.length === 0) {
this.havemore = false;
return;
}
if (this.recommends.length === 0) {
this.recommends = result.res.homepage[1].items;
this.monthes = result.res.homepage[2];
this.monthes.MM = moment(this.monthes.stime).format("MM");
this.monthes.DD = moment(this.monthes.stime).format("DD");
}
this.hots = [...this.hots, ...result.res.vertical];
});
},
handleToLower: function() {
if (this.havemore) {
this.params.skip += this.params.limit;
this.getList();
} else {
uni.showTabBar({
title: "到底了",
icno: "none",
});
}
},
},
};
</script>
<style lang="scss" scoped>
.recommend_view {
height: calc(100vh - 36px);
}
.recommend_wrap {
display: flex;
flex-wrap: wrap;
.recommend_item {
width: 50%;
border: 5rpx solid #fff;
}
}
.moneths_wrap {
.moneths_title {
display: flex;
justify-content: space-between;
padding: 20rpx;
.moneths_title_info {
display: flex;
.moneths_info {
color: $themeColor;
font-weight: 600;
text {
font-size: 36rpx;
}
}
.moneths_text {
padding-left: 15rpx;
font-weight: 600;
font-size: 34rpx;
color: #666;
}
}
.moneths_title_more {
font-size: 24rpx;
color: $themeColor;
font-weight: 600;
}
}
.moneths_content {
display: flex;
flex-wrap: wrap;
.moneths_item {
width: 33.33%;
border: 5rpx solid #fff;
}
}
}
.hots_wrap {
.hots_title {
padding: 20rpx;
text {
padding-left: 20rpx;
border-left: 10rpx solid $themeColor;
font-size: 30rpx;
font-weight: 600;
}
}
.hots_content {
display: flex;
flex-wrap: wrap;
.hot_item {
width: 33.33%;
border: 5rpx solid #fff;
}
}
}
</style>视频图片下载功能
async handledownload() {
await uni.showLoading({ title: "下载中" });
const { temFilePath } = (
await uni.downloadFile({ url: this.videoObj.video })
)[1];
await uni.saveVideoToPhotosAlbum({
filePath: temFilePath,
});
uni.hideLoading();
await uni.showToast({
title: "下载成功",
});
},页面展示
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 趁年轻!
评论