小程序开发笔记
今天开始接触了小程序开发,直接上手做有点费劲,找个项目学着先做一遍吧….
**笔记中的项目内容部分来自b站up主咸虾米_
分享的vue3+uniapp
学习内容 **
记录下一些基础内容,不熟练容易忘
pages
目录下放小程序页面内容
static
静态文件
pages.json
配置页面路由、导航栏、tabBar等页面类信息
在pages.json中,pages是页面路由及窗口表现,globalStyle是默认(全局)窗口表现,tabBar是下面的tab栏,至少要两个才会展示
manifest.json
配置appid、应用名、logo、版本等打包信息
在manifest.json里面配置了appid后,微信开发工具的预览模式才能使用
swiper
轮播图的使用,自动轮播,无缝衔接,点击查看预览
<template> <swiper class="banner" indicator-dots :autoplay="false" circular> <swiper-item v-for="item in pictures" :key="item.id"> <image :src="item.url" @tap="onPreviewImage(item.url)" /> </swiper-item> </swiper> </template>
<script> export default { data() { return { // 轮播图 pictures: [ { id: 1, url: 'https://xxx' }, { id: 2, url: 'https://xxx'} ] } }, onLoad() { }, methods: { onPreviewImage(url) { // console.log(url) uni.previewImage({ urls: this.pictures.map(item => item.url), current: url }) } } } </script>
<style> .banner { width: 750rpx; height: 750rpx; } .banner image { width: 750rpx; height: 750rpx; } </style>
|
使用即时设计进行尺寸测量
切片工具
可以用来测量字号、图片尺寸等



设置全局样式文件
项目目录中有一个文件叫uni.scss
,这个就是小程序的全局样式文件,修改这个文件后想要使用其中变量需要重新启动项目
为了让内容干净,这里另写一个文件,然后再uni.scss
中引用
@import "@/common/style/base-style.scss";
|
banner海报swiper
轮播器
实现效果

代码如下
<template> <view class="homeLayout pageBg"> <view class="banner"> <swiper indicator-dots indicator-color="rgba(255,255,255,0.5)" indicator-active-color="#fff" autoplay circular> <swiper-item v-for="item in imageList"> <image :src="item" mode="aspectFill"></image> </swiper-item> </swiper> </view> </template>
<script setup> // 随便弄几张图 const imageList = ['../../common/images/banner1.jpg', '../../common/images/banner2.jpg', '../../common/images/banner3.jpg'] </script>
<style lang="scss" scoped> .banner { width: 750rpx; padding: 30rpx 0;
swiper { width: 750rpx; height: 340rpx;
&-item { width: 100%; height: 100%; padding: 0 30rpx;
image { width: 100%; height: 100%; // 圆角 border-radius: 10rpx; } } }
} </style>
|
indicator-dots
是轮播小圆点,indicator-color
设置颜色,indicator-active-color
是选中时的颜色,autoplay
自动轮播,circular
循环轮播
使用图片时,设置mode="aspectFill"
让他撑满区域
使用swiper
纵向轮播做公告区域
实现效果


代码内容
<template> <view class="notice"> <view class="left"> <uni-icons type="sound-filled" size="20"></uni-icons> <text class="text">公告</text> </view> <view class="center"> <swiper vertical autoplay interval="1500" duration="300" circular> <swiper-item v-for="item in 4">文字内文字文字文字文字文字文字文字文字容</swiper-item> </swiper> </view> <view class="right"> <uni-icons type="right" size="16" color="#333"></uni-icons> </view> </view> </template>
<style lang="scss" scoped> .notice { width: 690rpx; height: 80rpx; line-height: 80rpx; background: #f8f8f8; margin: 0 auto; border-radius: 80rpx; display: flex; .left { width: 140rpx; display: flex; align-items: center; justify-content: center; :deep() { .uni-icons { color: $brand-theme-color !important; } }
.text { color: $brand-theme-color; font-weight: 600; font-size: 28rpx; } } .center { flex: 1; swiper { height: 100%; &-item { height: 100%; font-size: 30rpx; color: #666; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } } } .right { width: 70rpx; display: flex; align-items: center; justify-content: center; } } </style>
|
<uni-icons>
是uniapp的图标组件,使用的话需要安装,基本用法如下
<uni-icons type="contact" size="30"></uni-icons>
|
type
是图标类型,size
图标大小,可以根据文档添加其他参数,如color
修改图标颜色等
主要通过样式实现排列,其中display
、align-items
,justify-content
的设置保证元素所在位置居中,会经常使用
display: flex; align-items: center; justify-content: center;
|
在最外层添加了border-radius
圆角,内部元素必须进行相关设置以展示圆角,比如上面在swiper-item
设置的overflow: hidden;
另外,为公告部分内容添加了省略号的处理
white-space: nowrap; text-overflow: ellipsis;
|
实现效果

代码内容
<template> <view class="homeLayout pageBg"> <view class="select"> <common-title> <template #name>每日推荐</template> <template #custom> <view class="date"> <uni-icons type="calendar" size="18"></uni-icons> <view class="text"> <uni-dateformat :date="Date.now()" format="dd日"></uni-dateformat> </view> </view> </template> </common-title> <view class="content"> <scroll-view scroll-x> <view class="box" v-for="item in 8"> <image src="../../common/images/preview_small.webp" mode="aspectFill"></image> </view> </scroll-view> </view> </view> </view> </template>
<style lang="scss" scoped> .homeLayout { .select { padding-top: 50rpx; .content { width: 720rpx; margin-left: 30rpx; margin-top: 30rpx; scroll-view { white-space: nowrap; .box { width: 200rpx; height: 430rpx; display: inline-block; margin-right: 15rpx; image { width: 100%; height: 100%; border-radius: 10rpx; } } .box:last-child { margin-right: 30rpx; } } } .date { color: $brand-theme-color; display: flex; align-items: center; :deep() { .uni-icons { color: $brand-theme-color !important; } } .text { margin-left: 5rpx; } } } } </style>
|
具名插槽定义标题组件
添加了一个common-title
组件,用来设置样式
<template> <view class="common-title"> <view class="name"> <slot name="name"> </slot> </view> <view class="custom"> <slot name="custom"></slot> </view> </view> </template>
<script setup>
</script>
<style lang="scss" scoped> .common-title { display: flex; justify-content: space-between; align-items: center; padding: 0 30rpx; .name { font-size: 40rpx; } } </style>
|
这里分为上下两部分,上部分标题文字和日期,下部分是滑动组件
在上部分的日期这里,使用了uni-dateformat
组件,也是需要先去uniapp组件市场安装
<!-- 一般用法 --> <uni-dateformat date="2020/10/20 20:20:20"></uni-dateformat>
<!-- 不显示刚刚/马上/xx分钟前 --> <uni-dateformat date="2020/10/20 20:20:20" :threshold="[0,0]"></uni-dateformat>
|
下部分使用scroll-view
滚动条,指定scroll-x
横向滚动,其中内容暂时用一个图片的循环
<view class="box" v-for="item in 8"> <image src="../../common/images/preview_small.webp" mode="aspectFill"></image> </view>
|
为其设置white-space: nowrap;
阻止换行
统一设置了右边距margin-right: 15rpx;
,让每一个元素之间间隔15rpx,但是当滚动到最后一个元素时,右边距仍然为15rpx,而父元素左边距为30rpx,看起来不协调,所以单独调整最后一个元素的右边距
.box { width: 200rpx; height: 430rpx; display: inline-block; margin-right: 15rpx;
image { width: 100%; height: 100%; border-radius: 10rpx; } } .box:last-child { margin-right: 30rpx; }
|
磨砂背景 + 定位布局做专题组件
实现效果

代码内容
<template> <view class="theme"> <common-title> <template #name>专题精选</template> <template #custom> <navigator url="" class="more">more</navigator> </template> </common-title> <view class="content"> <theme-item v-for="item in 8"></theme-item> <theme-item :isMore="true"></theme-item> </view> </view> </template>
<script setup> </script>
<style lang="scss" scoped> .theme { padding: 50rpx 0;
.more { font-size: 32rpx; color: $text-font-color-3; }
.content { margin-top: 30rpx; padding: 0 30rpx; display: grid; gap: 15rpx; grid-template-columns: repeat(3, 1fr); } } </style>
|
其中组件theme-item
<template> <view class="themeItem"> <navigator url="/pages/classlist/classlist" class="box" v-if="!isMore"> <image class="pic" src="../../common/images/classify1.jpg" mode="aspectFill"></image> <view class="mask">明星美女</view> <view class="tab">3天前更新</view> </navigator> <navigator url="/pages/classify/classify" open-type="reLaunch" class="box more" v-if="isMore"> <image class="pic" src="../../common/images/more.jpg" mode="aspectFill"></image> <view class="mask"> <uni-icons type="more-filled" size="34" color="#fff"></uni-icons> <view class="text">更多</view> </view> </navigator> </view> </template>
<script setup> defineProps({ isMore: { type: Boolean, default: false } }) </script>
<style lang="scss" scoped> .themeItem { .box { height: 340rpx; border-radius: 10rpx; overflow: hidden; position: relative; .pic { width: 100%; height: 100%; } .mask { width: 100%; height: 70rpx; position: absolute; bottom: 0; left: 0; background: rgba(0, 0, 0, 0.2); color: #fff; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(20rpx); font-weight: 600; font-size: 30rpx; } .tab { position: absolute; left: 0; top: 0; background: rgba(250, 129, 90, 0.7); backdrop-filter: blur(20rpx); color: #fff; font-size: 22rpx; padding: 6rpx 14rpx; border-radius: 0 0 20rpx 0; transform: scale(0.8); transform-origin: left top; } } .box.more { .mask { width: 100%; height: 100%; flex-direction: column; } .text { font-size: 28rpx; } } } </style>
|
首先,主页面中content
部分,使用gird
布局,grid-template-columns
中,repeat(3, 1fr)
表示创建3列,其中每份占据1/3空间,gap
表示内容间距为15rpx
.content { margin-top: 30rpx; padding: 0 30rpx; display: grid; gap: 15rpx; grid-template-columns: repeat(3, 1fr); }
|
然后是组件中内容,根据父组件传递的参数isMore
判断生成的内容,父组件中先循环了8次,且没有传递isMore
,则默认生成图片为classify1.jpg
的navigator
跳转区域,这部分有一个遮罩的部分,使用定位设置遮罩位于父组件最下面区域,然后设置了遮罩的background
为rgba(0, 0, 0, 0.2)
是一个黑色的半透明区域,但是半透明还是可以看到遮罩后的内容的,所以添加backdrop-filter: blur(20rpx);
为遮罩添加了一个模糊效果
.mask { width: 100%; height: 70rpx; position: absolute; bottom: 0; left: 0; background: rgba(0, 0, 0, 0.2); color: #fff; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(20rpx); font-weight: 600; font-size: 30rpx; }
|
父组件循环8次后,单独定义了一个theme-item
,并且传参isMore
为true
,生成了内容为more.jpg
跳转区域,并设置了单独的遮罩样式,这部分作为更多选项,所以遮罩设置为整个图片的遮罩,里面添加了一个。。。
的的图标和更多
文字,我希望他们竖向排列,所以修改flex
布局为竖向flex-direction: column;
,其余样式延用公共定义box
或mask
的样式,只有被box
和more
同时修饰的元素才适用这些个性的样式
.box.more { .mask { width: 100%; height: 100%; flex-direction: column; } .text { font-size: 28rpx; } }
|
点击更多时,希望跳转到分类的页面,但是分类位于tabBar
中,默认是不允许跳转的,需要为navigator
添加open-type="reLaunch"
<navigator url="/pages/classify/classify" open-type="reLaunch" class="box more" v-if="isMore"> <image class="pic" src="../../common/images/more.jpg" mode="aspectFill"></image> <view class="mask"> <uni-icons type="more-filled" size="34" color="#fff"></uni-icons> <view class="text">更多</view> </view> </navigator>
|
个人中心页面布局
头部logo部分
实现效果

代码内容
<template> <view class="userInfo"> <view class="avatar"> <image src="../../static/images/xxmLogo.png" mode="aspectFill"></image> </view>
<view class="ip">100.100.100.100</view>
<view class="address">来自于: 山东</view> </view> </template> <script setup>
</script>
<style lang="scss" scoped> .userInfo { display: flex; align-items: center; justify-content: center; flex-direction: column; padding: 50rpx 0;
.avatar { width: 160rpx; height: 160rpx; border-radius: 50%; overflow: hidden;
image { width: 100%; height: 100%; } }
.ip { font-size: 44rpx; color: #333; padding: 20rpx 0 5rpx; }
.address { font-size: 28rpx; color: #aaa; } } </style>
|
通过样式调整头像、ip和地址的效果
内容部分
实现效果

代码内容
<template> <view class="section"> <view class="list"> <navigator url="/pages/classlist/classlist" class="row"> <view class="left"> <uni-icons type="download-filled" size="20"></uni-icons> <view class="text">我的下载</view> </view>
<view class="right"> <view class="text">33</view> <uni-icons type="right" size="15" color="#aaa"></uni-icons> </view> </navigator> <navigator url="/pages/classlist/classlist" class="row"> <view class="left"> <uni-icons type="star-filled" size="20"></uni-icons> <view class="text">我的评分</view> </view> <view class="right"> <view class="text">33</view> <uni-icons type="right" size="15" color="#aaa"></uni-icons> </view> </navigator> <view class="row"> <view class="left"> <uni-icons size="20"></uni-icons> <view class="text">联系客服</view> </view> <view class="right"> <uni-icons type="right" size="15" color="#aaa"></uni-icons> </view> </view> </view> </view> </template> <script setup> </script>
<style lang="scss" scoped> .section { width: 690rpx; margin: 50rpx auto; border: 1px solid #eee; border-radius: 10rpx; box-shadow: 0 0 30rpx eeergba(0, 0, 0, 0.05); :deep() { .uni-icons { color: $brand-theme-color !important; } }
.list { .row { background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 30rpx; height: 100rpx; border-bottom: 1px solid #eee; position: relative;
&:last-child { border-bottom: 0; }
.left { display: flex; align-items: center;
.text { padding-left: 20rpx; color: #666; } }
.right { display: flex; align-items: center;
.text { font-size: 28rpx; color: #aaa;
} } } } } </style>
|
每行的内容可以分为三个部分:内容图标、文字和最右侧的>
,同时最右侧可能会有数字
那么将每一行分为左右两部分,.row
中的justify-content: space-between;
会让子元素会均匀地分布在容器内,第一个元素和最后一个元素贴靠容器的两端,中间的元素则根据可用空间均匀分布。
联系客服的功能,想要做成在小程序点击联系客服,在h5点击时拨打电话的,之后再说
#ifdef
实现多端客服
代码内容
<template> <view class="row"> <view class="left"> <uni-icons type="chatboxes-filled" size="20"></uni-icons> <view class="text">联系客服</view> </view> <view class="right"> <uni-icons type="right" size="15" color="#aaa"></uni-icons> </view> <!-- #ifdef MP --> <button open-type="contact">联系客服</button> <!-- #endif --> <!-- #ifndef MP --> <button @click="clickContact">拨打电话</button> <!-- #endif --> </view> </template> <script setup> const clickContact = () => { uni.makePhoneCall({ phoneNumber: "114" }) } </script>
<style lang="scss" scoped> .list { .row { background: #fff; display: flex; align-items: center; justify-content: space-between; padding: 0 30rpx; height: 100rpx; border-bottom: 1px solid #eee; position: relative;
&:last-child { border-bottom: 0; }
.left { display: flex; align-items: center;
.text { padding-left: 20rpx; color: #666; } }
.right { display: flex; align-items: center;
.text { font-size: 28rpx; color: #aaa;
} } button { position: absolute; top: 0; left: 0; height: 100rpx; width: 100%; opacity: 0; } } } } </style>
|
联系客服功能,这里思路是将联系客服
这个区域都作为点击区域,那么直接弄一个透明的大按钮覆盖整个view
区域就可以了
小程序内自身有客服相关的api,首先需要在小程序管理平台设置客服

然后为button
添加open-type="contact"
即可
<button open-type="contact">联系客服</button>
|
在h5页面是无法点击后跳转联系客服的聊天的,所以设置在h5点击时拨打电话,也可以在uniapp找的相关接口

再写另外一个按钮并且给他绑定点击事件
<button @click="clickContact">拨打电话</button>
<script setup> const clickContact = () => { uni.makePhoneCall({ phoneNumber: "114" }) } </script>
|
这样的话功能就实现了,那么接下来要控制他们分别在该生效的时候生效,就要用到#ifdef
控制了
#ifdef
和 #ifndef
是用于条件编译的指令。它们用于根据不同的平台或环境执行特定的代码块,从而在多平台或跨平台应用开发中提供灵活的代码处理机制。
常见平台标识符:
- **
MP
**:通用小程序(包括微信、支付宝、百度等多端小程序)。
- **
H5
**:H5 端(浏览器访问)。
- **
APP-PLUS
**:App 端(运行在 iOS 或 Android 上的应用)。
- **
WEIXIN
**:微信小程序。
- **
ALIPAY
**:支付宝小程序。
- **
MP-WEIXIN
**:专门用于微信小程序的标识符。
- **
MP-ALIPAY
**:专门用于支付宝小程序的标识符。
那么就可以设置是小程序时#ifdef MP
按钮功能是联系客服,不是小程序#ifndef MP
时是拨打电话功能
<!-- #ifdef MP --> <button open-type="contact">联系客服</button> <!-- #endif --> <!-- #ifndef MP --> <button @click="clickContact">拨打电话</button> <!-- #endif -->
|
最后在样式中设置button,宽度拉满,高度为100rpx
和row
相同,实现让整个按钮盖在整个联系客服
区域,设置opacity: 0;
,让按钮变得完全透明,实现需求
linear-gradient
设置全局渐变背景色
首先在小程序主文件App.vue
引入样式文件,可以在整个小程序中生效

然后写一个样式
.pageBg { background: linear-gradient(to bottom, transparent, #fff 400rpx), linear-gradient(to right, #beecd8 20%, #F4E2D8); min-height: 80vh; }
|
linear-gradient
是 CSS 中用于创建线性渐变的函数。它可以让一种颜色平滑地过渡到另一种颜色,并且这种渐变可以在不同的方向上进行,比如从上到下、从左到右、或者任意角度。
linear-gradient
基本语法
background: linear-gradient(direction, color-stop1, color-stop2, ...);
|
- **
direction
**:定义渐变的方向(默认是从上到下)。
- **
color-stop
**:指定渐变的颜色及其位置(可选)。如果不指定位置,颜色会均匀分布。
方向(Direction)
- 关键字:
to top
:从下到上渐变。
to bottom
:从上到下渐变(默认方向)。
to left
:从右到左渐变。
to right
:从左到右渐变。
background: linear-gradient(to right, red, blue);
|
角度: 角度值表示从水平线开始顺时针旋转的角度。0deg
是从下到上,90deg
是从左到右。
0deg
:从下到上渐变。
90deg
:从左到右渐变。
180deg
:从上到下渐变。
270deg
:从右到左渐变。
background: linear-gradient(45deg, red, blue);
|
颜色停止点(Color Stops)
每个渐变都至少需要两个颜色。颜色可以指定渐变的开始和结束位置,位置可以是百分比或长度值(如 px
, em
)。
- 颜色:颜色可以用常见的色值表示法,如名字(
red
)、十六进制(#ff0000
)、RGB(rgb(255,0,0)
)等。
- 位置:可选项,表示颜色在哪个位置开始或结束渐变。如果不指定,颜色会根据数量平均分布。
background: linear-gradient(to right, red 0%, blue 100%);
|
更复杂的就不说了
这个是可以添加多个的,写多个linear-gradient
就可以让渐变叠加
其中pageBg中的第一个渐变是从上到下的透明到白色渐变,第二个渐变是从左到右的绿色到米色渐变
linear-gradient(to bottom, transparent, #fff 400rpx), linear-gradient(to right, #beecd8 20%, #F4E2D8);
|
最后为每个页面加上这个样式就可以了
<template> <view class="xxxstyle pageBg"> </view> </template>
|
路由页面跳转
这个简单,直接给navigator
添加url
就行了
<navigator url="/pages/classlist/classlist" class="row">
|
代码内容
<template> <uni-popup ref="scorePopup"> <view class="scorePopup"> <view class="popHeader"> <view></view> <view class="title">壁纸评分</view> <view class="close" @click="clickScoreClose"> <uni-icons type="closeempty" size="18" color="#999"></uni-icons> </view> </view> </view> </uni-popup> </template>
<script setup> import { ref } from 'vue';
const scorePopup = ref(null)
// 打开评分弹窗 const clickScore = () => { scorePopup.value.open(); } // 关闭评分弹窗 const clickScoreClose = () => { scorePopup.value.close(); } </script>
|
首先要安装uni-popup
的插件,官方文档的使用方法如下,这是vue2
的写法
<template> <view> <button @click="open">打开弹窗</button> <uni-popup ref="popup" type="bottom" border-radius="10px 10px 0 0">底部弹出 Popup 自定义圆角</uni-popup> </view> </template> <script> export default { methods:{ open(){ // 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center'] this.$refs.popup.open('top') } } } </script>
|
哈哈,太久没写,挖坟了