制作APP学习记录
文章初衷
因为想要学做一款自己的app,app里面添加自己想要的功能,集自己的需求于一款app里。
记录学习Flutter制作APP的过程和知识点
2024年
10.19
分类页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<template>
<!-- 大模块 -->
<view class="classLayout">
<view class="classify">
<theme-item v-for="item in 15"></theme-item>
</view>
</view>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.classify{
padding: 30rpx;
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 15rpx;
}
</style>我的页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166<template>
<view class="userLayout">
<view class="userInfo">
<view class="avatar">
<image src="../../static/logo.png" mode="aspectFill"></image>
</view>
<view class="ip">100.100.100.100</view>
<view class="address">来自于:山东</view>
</view>
<view class="section">
<view class="list">
<view class="row">
<view class="left">
<uni-icons type="download-filled" size="20" color="#28b389"></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>
</view>
<view class="row">
<view class="left">
<uni-icons type="star-filled" size="20" color="#28b389"></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>
</view>
<view class="row">
<view class="left">
<uni-icons type="chatboxes-filled" size="20" color="#28b389"></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>
</view>
</view>
<view class="section">
<view class="list">
<view class="row">
<view class="left">
<uni-icons type="notification-filled" size="20" color="#28b389"></uni-icons>
<view class="text">订阅更新</view>
</view>
<view class="right">
<uni-icons type="right" size="15" color="#aaa"></uni-icons>
</view>
</view>
<view class="row">
<view class="left">
<uni-icons type="flag-filled" size="20" color="#28b389"></uni-icons>
<view class="text">常见问题</view>
</view>
<view class="right">
<uni-icons type="right" size="15" color="#aaa"></uni-icons>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
const clickContact=()=>{
uni.makePhoneCall({
phoneNumber:"000"
})
}
</script>
<style lang="scss" scoped>
.userLayout{
.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;
}
}
.section{
width: 690rpx;
margin: 50rpx auto;
border: 1px solid #eee;
border-radius: 10rpx;
box-shadow: 0 0 30rpx rgba(0, 0, 0, 0.05);
.list{
.row{
display: flex;
// 两端对齐
justify-content: space-between;
align-items: center;
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{
padding-left: 28rpx;
color: #aaa;
}
}
button{
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
// 透明
opacity: 0;
}
}
}
}
}
</style>底部导航栏
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26"tabBar": {
// 导航栏文字颜色
"color": "#9799a5",
"selectedColor": "#28b398",
// 导航栏列表
"list": [
{
"text": "推荐",
"pagePath": "pages/index/index" ,
"iconPath": "static/images/tabBar/home.png",
"selectedIconPath": "static/images/tabBar/home-h.png"
},
{
"text": "分类",
"pagePath": "pages/classify/classify" ,
"iconPath": "static/images/tabBar/classify.png",
"selectedIconPath": "static/images/tabBar/classify-h.png"
},
{
"text": "我的",
"pagePath": "pages/user/user" ,
"iconPath": "static/images/tabBar/user.png",
"selectedIconPath": "static/images/tabBar/user-h.png"
}
]
},背景渐变
加载common-style.css里面当全局
1
2
3
4
5
6.pageBg{
background:
linear-gradient(to bottom,transparent,#fff 400rpx),
linear-gradient(to right,#beecd8 20%,#f4e2d8);
min-height: 80vh;
}颜色变量
1
2
3
4
5
6
7
8
9@import "common/style/base-style.scss"
// 穿刺
:deep(){
.uni-icons{
// 最高权重
color: $brand-theme-color !important;
}
}分类列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34<template>
<view class="classlist">
<view class="content">
<navigator url="" class="item" v-for="item in 10">
<image src="../../common/images/preview2.jpg" mode="aspectFill"></image>
</navigator>
</view>
</view>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.classlist{
.content{
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 5rpx;
padding: 5rpx;
.item{
height: 440rpx;
image{
width: 100%;
height: 100%;
display: block;
}
}
}
}
</style>
10.18
做完了首页界面
common-title
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29<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>theme-item
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89<template>
<view class="themeItem">
<navigator url="" 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="" 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;
// 图片盖住box圆角,所以设置hidden
overflow: hidden;
// 定位
position: relative;
.pic{
width: 100%;
height: 100%;
}
// 图库标记
.mask{
width: 100%;
height: 70rpx;
// 定位文字位置
position: absolute;
bottom: 0;
left: 0;
background: rbga(0,0,0,0.2);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(50rpx);
font-weight: 600;
font-size: 35rpx;
}
// 更新信息
.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>- index
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194<template>
<view class="homeLayout">
<!-- 轮播图 -->
<view class="banner">
<swiper circular indicator-dots indicator-color="rgba(255,255,255,0.5)"
indicator-active-color="#fff" autoplay>
<swiper-item>
<image src="../../common/images/banner1.jpg" mode=""></image>
</swiper-item>
<swiper-item>
<image src="../../common/images/banner2.jpg" mode=""></image>
</swiper-item>
<swiper-item>
<image src="../../common/images/banner3.jpg" mode=""></image>
</swiper-item>
</swiper>
</view>
<!-- 公告栏 -->
<view class="notice">
<view class="left">
<uni-icons type="sound-filled" size="20" color="#28b289"></uni-icons>
<text class="text">公告</text>
</view>
<view class="center">
<swiper vertical autoplay interval="1500" duration="300">
<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>
<!-- 图片展示区 -->
<view class="select">
<common-title>
<template #name>每日推荐</template>
<template #custom>
<view class="date">
<uni-icons type="calendar" size="18" color="#28b289"></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 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>
</view>
</template>
<script setup>
</script>
<style lang="scss">
.homeLayout{
.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;
}
}
}
}
.notice{
width: 690rpx;
height: 80rpx;
line-height: 80rpx;
background: #f9f9f9;
margin: 0 auto;
border-radius: 80rpx;
display: flex;
.left{
width: 140rpx;
// 水平垂直对齐
display: flex;
align-items: center;
justify-content: center;
.text{
color: #28b398;
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;
}
}
.select{
padding-top: 50rpx;
// 日期盒子
.date{
color: #28b398;
display: flex;
align-items: center;
.text{
margin-left: 5rpx;
}
}
.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;}
}
}
}
.theme{
//上下间隔50,左右为0
padding: 50rpx 0;
.more{
font-size: 32rpx;
color: #888;
}
.content{
margin-top: 30rpx;
padding:0 30rpx;
display: grid;
gap: 15rpx;
grid-template-columns: repeat(3,1fr);
}
}
}
</style>
学习过程中,我发现不懂的知识点可以问ai,ai会给出很好的答案,而且还会进行拓展,这样的话做笔记也可以直接复制,也很全面
另外手敲一遍代码也是很重要的,可以边敲边看页面的变化,熟悉每个属性。
配置自动导入模块
开发uniapp使用Vue3组合式API版本,如何实现从vue模块中自动导入_uniapp unplugin-auto-import-CSDN博客
所需知识学习视频
因为flutter上手门槛较高,所以改为用uniapp了
先去学了前端三件套,再学了vue。先掌握知识点大概,等遇到不会的再继续学习
前端
vue3
uniapp
Dart 语言开发文档
Flutter 官方文档
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Jcheng's Blog!