文章初衷

因为想要学做一款自己的app,app里面添加自己想要的功能,集自己的需求于一款app里。
记录学习Flutter制作APP的过程和知识点

2024年

10.19

  1. 分类页面

    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>
  2. 我的页面

    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>

  3. 底部导航栏

    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"
    }
    ]
    },
  4. 背景渐变

    加载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;
    }
  5. 颜色变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @import "common/style/base-style.scss"

    // 穿刺
    :deep(){
    .uni-icons{
    // 最高权重
    color: $brand-theme-color !important;
    }
    }
  6. 分类列表

    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

  1. 做完了首页界面

    1. 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>
    2. 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>
    1. 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。先掌握知识点大概,等遇到不会的再继续学习

前端

3小时前端入门教程(HTML+CSS+JS)

vue3

【2024最新版】Vue3从入门到精通,零基础小白也能听得懂

uniapp

零基础入门uniapp Vue3组合式API版本到咸虾米壁纸项目实战

Dart 语言开发文档

点击跳转

Flutter 官方文档

点击跳转