uni-app + uniCloud 入门与进阶

作者:user 发布日期: 浏览量:7

简介

uni-app 是什么:
- uni-app 是 DCloud 公司研发的使用 Vue.js 技术开发所有前端应用的框架
- uni-app 可以开发一套代码发布多个平台
- uni-app 有完整的生态,受企业青睐

uni-app 的优势是什么:
- 开发者/案例数量最多
- 平台能力不受限制:在跨端的同时,通过条件编译 + 平台特有 API 调用,可以优雅的为平台写个性化代码,调用专有能力而不影响其它平台;支持原生代码混写和原生SDK 集成
- 性能体验优秀
- 周边生态丰富:支持小程序组件和SDK、兼容 mpvue 组件和项目、兼容 weex 组件;微信生态的各种 SDK 可直接用于跨平台 APP
- 学习成本低:基于通用前端技术栈,采用 vue语法 + 微信小程序API
- 开发成本低

uni-app 和 vue 有什么关系:
- 使用 Vue.js 语法开发
- 在发布到 H5 时,支持所有 vue 的语法
- 发布到 App 和小程序时,实现部分 vue 语法

uni-app 和小程序有什么关系:
- 组件标签靠近小程序规范
- 接口能力(JS API)靠近微信小程序规范
- 完整的小程序生命周期

uni-app小知识:
- 一般 vue 项目使用页面组件时需要引入和注册,在 uni-app 可以不用引入和注册,因为有 easyCom 功能(局部引入),只要组件的新建时的结构是 components/组件名/组件名.vue
- 可以在 uni.scss 文件中自定义 scss 变量

一、uni-app 基础知识

1、uni-app 核心知识概览

uni-app 规范:
- 页面文件遵循 Vue 单文件组件(SFC)规范

// 模版块:一个页面只能有一个
<template>
    <view class="content">
        {{content}}
    </view>
</template>
// 脚本块:一个页面也只能有一个
<script>
    export default {
        data() {
            return {
                content: 'hello uni-app'
            }
        }
    }
</script>
// 样式块:可以有多个
<style>
    .content {
        background-color: #fff;
    }
</style>
  • 组件标签靠近小程序规范
// 普通 web 开发
<body>
    <div>
        <img src=""></img>
        <span></span>
    </div>
</body>

// ni-app 
<template>
    <view>
        <image src=""></image>
        <text></text>
    </view>
</template>
  • 接口能力(JS API)靠近微信小程序规范
onLoad() {
    // 获取网络类型
    uni.getNetWorkType()
}
  • 数据绑定及事件处理同 Vue.js 规范
  • 为兼容多端运行,建议使用 flex 布局进行开发

ni-app 特色:
- 条件编译

条件编译写法 说明
#ifdef APP-PLUS 需要条件编译的代码 #endif 仅出现在 App 平台下的代码
#ifdef H5 需要条件编译的代码 #endif 除了 H5 平台,其它平台均存在的代码
#ifdef H5 || MP-WEIXIN 需要条件编译的代码 #endif 在 H5 平台或微信小程序平台存在的代码
- App 端的 Nvue 开发
- HTML5+

uni-app 知识点:
- 组件
基础组件
自定义组件
- 生命周期
- API
路由:uni-app 没有路由的概念,只是页面切换
- 语法
布局样式

2、搭建 uni-app 开发环境

(1)使用 vue-cli 的方式运行项目(不推荐)

  • 首先安装有 node,安装 node 的教程网上很多了
// 查看 node 是否安装成功
node -v
  • 安装 vue 脚手架
npm install @vue-cli -g
// 或 npm install @vue/cli -g

// 查看 vue-cli 是否安装成功
vue -V
  • 安装 uni-app 工程:先进入要安装的目录
vue create -p dcloudio/uni-preset-vue 项目名称
  • 然后通过键盘上下键选择对应“模版”,回车即可
  • 运行项目
// cd 进入项目目录
cd 项目名称

// 运行项目
npm run serve

(2)安装并运行 HBuilderX

  • HBuilderX 官网下载地址:https://www.dcloud.io/hbuilderx.html
  • 下载的时候建议选择对应系统的“App开发版”
    在这里插入图片描述
  • 打开 HBuilderX 后新建项目选择 uni-app,然后填写“项目名称”、“项目路径”,选择对应“模版”就可以新建一个 uni-app 项目
    在这里插入图片描述

3、语法知识

(1)模版语法与数据绑定

  • 模版语法:使用双花括号“{{ 绑定的变量 }}”
  • 数据绑定:使用双花括号“{{ 绑定的变量 }}” 与 data() {} 函数中 return {} 的数据进行绑定
  • 动态绑定:使用 v-bind 指令绑定要绑定的属性(v-bind 简写:“:”)
  • 双向绑定:使用 v-model 指令
<view v-bind:class="className">
    hello uni-app
</view>
  • 绑定事件:使用 v-on 指令(v-on 简写:“@”)
  • 修改变量的值
// 在微信小程序中
this.setData({
    title: "hello"
})
// 在 uni-app 中
// this 指向当前 vue 的实例
this.title = "hello"

为什么 data 写成函数的形式而不是对象的形式:
- 如果使用对象的形式在运行项目的时候变量会保留上次的值,不会被初始化
- 而使用函数的形式可以保证每次进入页面时变量值都会刷新,不受前一次的影响

// 对象的形式
data: {
    "name": "hello world"
}

// 函数的形式
data() {
    return {
        name: "hello world"
    }
}

(2)条件判断(v-if、v-else-if、v-else)

  • 判断某一个或某一块元素是否要渲染
  • v-if 如果表达式返回值为 true,那么就会正常的渲染内容
<view>
    <view v-if="show === ‘uni-app’">uni-app</view>
    <view v-else-if="show === 'vue'">vue</view>
    <view v-else>hello world</view>
</view>

(3)列表渲染(v-for … in)

  • 通过数组来渲染列表
  • v-for … in 渲染列表,item 是被迭代的数组元素的别名,index 是数组下标的别名
<view>
    <view v-for="(item,index) in arr">{{ item }}</view>
</view>
  • 通过对象渲染列表
  • v-for … in 渲染列表,key 是被迭代对象的键的别名,value 是对象的值的别名,index 是对象索引的别名
<view>
    <view v-for="(key,value,index) in obj">{{key}} = {{value}} = {{index}}</view>
</view>

(4)基础组件的使用

(5)自定义组件的使用

(6)基础 API 的用法

uni.request({
    url: 'https://www.example.com/request', 
    data: {
        text: 'uni.request'
    },
    header: {
        'custom-header': 'hello' //自定义请求头信息
    },
    success: (res) => {
        console.log(res.data);
        this.text = 'request success';
    }
});
  • 上传
uni.chooseImage({
    success: (chooseImageRes) => {
        const tempFilePaths = chooseImageRes.tempFilePaths;
        uni.uploadFile({
            url: 'https://www.example.com/upload', 
            filePath: tempFilePaths[0],
            name: 'file',
            formData: {
                'user': 'test'
            },
            success: (uploadFileRes) => {
                console.log(uploadFileRes.data);
            }
        });
    }
});
  • 下载
const downloadTask = uni.downloadFile({
    url: 'http://www.example.com/file/test', 
    success: (res) => {
        if (res.statusCode === 200) {
            console.log('下载成功');
        }
    }
});

downloadTask.onProgressUpdate((res) => {
    console.log('下载进度' + res.progress);
    console.log('已经下载的数据长度' + res.totalBytesWritten);
    console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);

    // 测试条件,取消下载任务。
    if (res.progress > 50) {
        downloadTask.abort();
    }
});

(7)条件编译

  • 具体详情请参考官网:https://uniapp.dcloud.io/platform?id=条件编译
  • 使用条件编译的代码,只会在对应的平台上才会编译
  • 条件编译是在注释代码中写开始和结束的语句,在不同语法里注释写法不一样,js使用 \/\/ 注释、css 使用 \/* 注释 */、vue/nvue 模板里使用 \
  • #ifdef 表示只在满足条件的设备编译;#ifndef 表示在满足条件的不编译,其它平台都编译
<view>
    <!-- #ifdef H5 -->
    <text>表示这段文本只在 H5 中编译</text>
    <!-- #endif -->

    <!-- #ifndef H5 -->
    <text>表示这段文本除了 H5 平台其它平台都存在</text>
    <!-- #endif -->
</view>
<script>
    // #ifdef

    // #endif
</script>

<style>
    /* #ifdef */

    /* #endif */
</style>
  • 条件编译写法说明
条件编译写法 说明
#ifdef APP-PLUS 需要条件编译的代码 #endif 仅出现在 App 平台下的代码
#ifndef H5 需要条件编译的代码 #endif 除了 H5 平台,其它平台均存在的代码
#ifdef H5 || MP-WEIXIN 需要条件编译的代码 #endif 在 H5 平台或微信小程序平台存在的代码(这里只有 ||,不可能出现 \&\&,因为没有交集)
- 条件编译的值和平台
平台
APP-PLUS App
APP-PLUS-NVUE 或 APP-NVUE App nvue
H5 H5
MP-WEIXIN 微信小程序
MP-ALIPAY 支付宝小程序
MP-BAIDU 百度小程序
MP-TOUTIAO 字节跳动小程序
MP-QQ QQ小程序
MP-360 360小程序
MP 微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序/360小程序
QUICKAPP-WEBVIEW 快应用通用(包含联盟、华为)
QUICKAPP-WEBVIEW-UNION 快应用联盟
QUICKAPP-WEBVIEW-HUAWEI 快应用华为

(8)页面布局

  • uni-app 中没有 body 的概念,如果想设置类似 body 的样式,使用 page
<style>
    /* body */
    /* body {
        background-color: #eee;
    } */
    /* page */
    page {
        background-color: #eee;
    }
</style>
  • 尺寸单位可以使用:px、rem、Rex、vh、vw
<style>
    /* 尺寸单位 */
    font-size: 12px;   // 或 px、rem、Rex、vh、vw
</style>
  • 引入外部 CSS
<style>
    @import '../css/index.css'
</style>

4、生命周期

<script>
  export default {
    // 应用初始化完成触发一次,全局只触发一次
    onLaunch: function() {
        // 应用场景:登陆、获取全局变量
    },

    // 应用启动的时候,或者从后台进入前台会触发
    onShow: function() {

    },

    // 应用从前台进入后台时触发
    onHide: function() {}
  }
</script>
  • 页面生命周期:定义在页面中,完整页面生命周期见官网
<script>
  export default {
    data() {
        return {

        }
    },
    // 监听页面加载
    onLoad() {
        // 
    },

    // 监听页面显示:每次页面出现在屏幕上都会触发
    onShow() {

    },

    // 监听页面的初次渲染完成
    onReady() {
        // 如果渲染速度快,会在页面进入动画完成前触发
    }

    // 监听页面隐藏:页面退出屏幕时触发
    onHide() {

    },

    // 监听页面卸载:
    onUnload() {

    },

    methods: {

    }
  }
</script>
  • 组件生命周期,完整组件生命周期见官网
<script>
  export default {
    // 在实例初始化之后,数据观测(data observer)和 event/watcher 事件配置之前被调用
    beforeCreate() {},

    // 实例创建完成之后立即调用,挂载阶段还没开始
    created() {},

    // 挂载到实例上之后调用
    mouted() {},

    // Vue 实例销毁后调用
    destroyed() {}
  }
</script>

二、uni-app 基础配置

1、微信小程序

  • 下载微信开发者工具地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
  • 首先扫码打开微信开发者工具,进入“设置” -> “安全设置”,然后打开“服务端口”
    在这里插入图片描述
    在这里插入图片描述
  • 打开 HBuilderX,点击左上角“HBuilderX” -> “偏好设置”,会打开“Settings.json”,点击“运行配置”,向下拉找到“小程序运行配置”,点击右侧的“浏览”找到开发者工具路径(或者手动填写开发者工具路径)
    在这里插入图片描述
  • 将项目运行到微信开发者工具:点击下列图片中的“运行图标”,选择“微信开发者工具”即可
  • 如果编译出错,可以将微信开发者工具关闭并重试;或者将微信开发者工具升级到最新稳定版本
    在这里插入图片描述

2、App 真机、模拟器

(1)App 真机

连接安卓设备(下列用vivo,其它安卓设备类似):
- 数据线连接手机和电脑
- 打开手机“设置” -> “关于手机” -> “版本号(或软件版本号)”,点击 5 次“版本号”进入开发者模式,待手机提示“您已处于开发者模式”后,返回上一级菜单进入“开发者选项”,开启“USB调试”开关(打开“USB调试”,选择“传输文件”)
- 然后就可以运行到手机或模拟器(过程中手机如需下载HBuilder,直接下载安装即可)
在这里插入图片描述

连接 ios 设备:
- 手机和电脑通过数据线连接后,同样打开 HBuilderX -> “运行到手机或模拟器”,如上图显示安卓设备信息的位置会显示“运行-(设备:iPhone-iOS) - (uni-app-test)”
- 如果没有正常显示,可以下载安装一个 iOS 手机助手

(2)模拟器(对于 Mac 电脑)

  • 可以到 App store 下载一个 Xcode
  • 然后打开 Xcode,点击左上角“Xcode” -> “Preferences(系统偏好设置)” -> “Components”,选择模拟器版本,安装
  • 安装完成之后重启 HBuilderX,点击“运行图标” -> “运行-(模拟器:iPhone) - (uni-app-test)”

3、H5

  • 打开 HBuilderX,点击“偏好设置” -> “运行配置” -> “浏览器运行配置”,填写 Chrome 或 Firefox 浏览器的安装路径即可
    在这里插入图片描述
  • 运行:点击“运行图标”,选择“Chrome 运行”
    在这里插入图片描述

4、uni-app 目录结构概述

在这里插入图片描述
- .hbuilderx/launch.json 文件:配置了启动调试时相关设置
- components 目录:用于存放组件的文件夹,自定义组件或从外部引入的组件放在该目录下
- pages 目录:用来存放所有页面的文件夹,等同于 Vue 开发中的 views
- static 目录:静态文件资源目录,例如存放图片
- unpackaged/dist 目录:编译后的文件存放目录,有些新建项目目录中没有这个目录,但只要在微信开发者工具等编译平台运行后,就会自动生成
- utils 目录:公用的工具类目录
- common 目录:公用的文件目录
- App.vue 文件:页面入口文件
- main.js 文件:应用入口文件,主要用来初始化 Vue 实例并使用需要的插件
- manifest.json 文件:应用配置文件,用于指定应用的名称、图标、权限等
- pages.json 文件:页面配置,是全局配置文件,可以配置页面路径、窗口样式、原生的导航栏、底部的 Tab 栏等
- uni.scss 文件:是 uni-app 的样式包,在其它文件中可以快速引入样式包的样式,如果使用 Sass 开发,可以使用里面提供的 sass 变量

5、配置项目底部选项卡(pages.json)

{
    "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
        {
            "path": "pages/index/index",
            "style": {
                "navigationBarTitleText": "uni-app"
            }
        }
    ],
    "globalStyle": {
        "navigationBarTextStyle": "black",
        "navigationBarTitleText": "uni-app",
        "navigationBarBackgroundColor": "#F8F8F8",
        "backgroundColor": "#F8F8F8"
    },
    "tabBar": {
    "color": "#7A7E83",  // tab 上的文字默认颜色
    "selectedColor": "#3cc51f",  // tab 上的文字选中时的颜色
    "borderStyle": "black",  // tabbar 上边框的颜色,可选值 black/white
    "backgroundColor": "#ffffff",  // tab 的背景色
    "list": [{ // tab 的列表,详见 list 属性说明,最少2个、最多5个 tab
        "pagePath": "pages/component/index", // 页面路径,必须在 pages 中先定义
        "iconPath": "static/image/icon_component.png",  // 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 position 为 top 时,此参数无效,不支持网络图片,不支持字体图标
        "selectedIconPath": "static/image/icon_component_HL.png",  // 选中时的图片路径
        "text": "组件". // tab 上按钮文字,在 App 和 H5 平台为非必填。例如中间可放一个没有文字的+号图标
    }, {
        "pagePath": "pages/API/index",
        "iconPath": "static/image/icon_API.png",
        "selectedIconPath": "static/image/icon_API_HL.png",
        "text": "接口"
  }]
  }
}

6、在 uni-app 中如何使用 Sass

(1)安装插件

  • 打开 HBuilderX,点击“工具” -> “插件安装”
    在这里插入图片描述
  • “安装新插件” -> “前往插件市场”
    在这里插入图片描述
  • “搜索” -> “下载”
    在这里插入图片描述
  • 使用 HBuilderX 导入插件(需要注册登陆)
    在这里插入图片描述

(2)Sass 插件的使用

  • 样式可以嵌套使用
  • 可以使用 Sass 变量
  • \& 可以表示父级
<template>
    <view class="test">
        <view class="test2">
            <view class="content">content</view>
        </view>
    </view>
</template>
<style>
    $uni-width: 200px;
    .test {
        color: red;
        .test2 {
            font-size: 12px;
            .content {
                line-height: 12px;
                // width: 200px; 可以替换为
                width: $uni-width;
            }
        }
    }
</style>

三、uniCloud 基础用法

1、认识 uniCloud

  • uniCloud 是 DCloud 联合阿里云和腾讯云为 uni-app 的开发者提供的一个基于 serverless 模式和 JS 编程的云开发平台
  • uniCloud 使用 JavaScript 开发前后台整体业务,对前端开发人员比较友好
  • uniCloud 可以使开发人员只需专注于业务开发,无需关心服务器运维
  • 对于非 H5,免域名使用服务器

uniCloud 构成:
- 云函数
- 云数据库
- 云存储和CDN

2、在 HBuilderX 中配置 uniCloud

  • 首先注册登陆 HBuilderX
  • 创建一个 uni-app 项目,并勾选“启用uniCloud”,然后勾选右侧的“阿里云”或“腾讯云”
    在这里插入图片描述
  • 点击“manifest.json”,找到“基础配置”,然后获取“uni-app应用标识”
    在这里插入图片描述
  • 在项目中的“uniCloud”右键选择“关联云服务空间或项目”
    在这里插入图片描述
  • 对于第一次使用 uniCloud 的,选择“新建”,然后会打开 DCloud 的云端网页,按照要求认证即可……
    在这里插入图片描述
  • 购买云服务器时,对于初学者购买免费的即可,免费的服务器可以免费使用一个月
    在这里插入图片描述
    在这里插入图片描述
  • 创建好云服务空间后,再次在“uniCloud”右键选择“关联云服务空间或项目”,然后点击云服务号,再点击“关联”即可
    在这里插入图片描述
    在这里插入图片描述
  • 最后就可以在“cloudfunctions”目录下新建云函数了,在新建好的云函数上右键,同样可以将云函数上传部署
    在这里插入图片描述

3、使用 uniCloud 的 Web 控制台

4、云函数

  • 云函数就是运行在云端(服务器端)的函数,每次修改云函数都要上传部署才能起作用
  • event 为客户端上传的参数
  • context 包含调用信息和运行状态,获取每次调用的 上下文
'use strict';
exports.main = async (event, context) => {
    //event为客户端上传的参数
    console.log('event : ', event)

    //返回数据给客户端
    return event
};
  • 可以在页面中使用 uni.callFunction({}) 调用云函数
methods: {
    函数名() {
        uniCloud.callFunction({
            name: "云函数名",
            data: {},
            success(res) {},
            fail(err) {}
        })
    }
}

5、云数据库

  • uniCloud 提供 JSON 格式的文档型数据库,数据库中的每条数据都是以 json 格式的对象,数据库可以有多个集合
  • 数据都是标准 JSON 代码,字符串需使用双引号
  • 鉴于安全考虑,云数据库的调用只能在云函数中进行,不能在客户端进行增、删、改、查
  • 在云函数中,可以通过 uniCloud.database() 获取数据库的引用
  • 集合的引用可以通过 数据库的引用.collection() 获取
  • 新增数据:collection.add()
  • 删除数据:collection.doc(‘该条记录的ID’).remove()
  • 修改数据:collection.doc(‘该条记录的ID’).update() 或 collection.doc(‘该条记录的ID’).set()
    update():只能更新ID存在的记录,对于ID不存在的记录更新不成功
    set():如果记录存在,则更新;如果不存在,则新增
  • 查询数据:
'use strict';

// 获取数据库的引用
const db = uniCloud.database()

exports.main = async (event, context) => {
    // 获取集合的引用
    const collection = db.collection('集合的名字')

    // 新增数据
    // 新增 1 条记录
    let res1 = await collection.add({
        name: "zs"
    })
    // 新增 多 条记录
    let res2 = await collection.add([
        {
            name: "lisi",
            age: 12
        },
        {
            name: "wangwu"
        }
    ])

    // 删除记录
    const res3 = await collection.doc('该条记录的ID').remove()

    // 修改记录
    const res4 = await collection.doc('该条记录的ID').update()
    const res5 = await collection.doc('该条记录的ID').set()

    // 查询记录
    // 查询指定ID的记录
    const res6 = await collection.doc('该条记录的ID').get()
    // 查询指定字段的记录
    const res6 = await collection.where(查询条件).get()

    //返回数据给客户端
    return event
};
  • 因为不可能每次修改云函数都要上传部署并在页面中调用测试,所以在对云函数进行操作时可以直接“上传并运行”云函数,然后在控制台查看测试结果
    在这里插入图片描述

6、云存储

  • 上传文件
methods: {
    addImage() {
        let count = 9 - this.imageLists.length
        let that = this
        uni.chooseImage({
            count: count,
            success(res) {
                const tempFilePaths = res.tempFilePaths
                tempFilePaths.forEach((item, index) => {
                    // 处理 H5 多选的状况
                    if (index < count) {
                        that.imageLists.push({
                            url: item
                        })
                    }
                })
            }
        })
    },

    async submit() {
        let imagesPath = []
        // uni.showLoading()
        for (let i = 0; i < this.imageLists.length; i++) {
            const filePath = this.imageLists[i].url
            this.uploadFiles(filePath)
        }
    },
    async uploadFiles(filePath) {
        const result = await uniCloud.uploadFile({
            cloudPath: new Date(),
            filePath: filePath
        })
        return result.fileID
    },

    // 删除云存储中的文件
    uniCloud.deleteFile({
        fileList: ['云存储中的下载地址'],
        success(res) {
            console.log(res)
        },
        fail(err) {
            console.log(err)
        }
    })
}

四、知识全面提升

1、单文件组件

  • uni-app 是基于 Vue 的一套全端解决方案,uni-app 页面文件的开发规范遵循的是 Vue 单文件组件(SFC)规范

什么是 Vue 的单文件组件:
- 在 Vue 中,每一个以 .vue 结尾的文件都是一个单文件组件
- 每一个单文件组件主要包含三大块:\、\、\
- 在创建好一个 .vue 文件后,vue-loader 会解析文件并提取每一个语言模块,将它们组装成一个 CommonJS 模块,默认会导出一个组件对象

使用 uni-app 创建一个页面:
- 在新建的页面中,会默认创建单文件组件的三个模块
- 在 template 中只支持单个根节点(虽然 Vue3 支持多个根节点),而且根标签与 Vue 不同,Vue 使用的是 \

,而 uni-app 使用的是 \
- script 模块,每一个 .vue 文件只能包含一个\ 标签,页面的实现逻辑放在 \ 标签内
- style 模块,与 script 模块不同,一个 .vue 文件可以包含多个 \标签
- 在三个模块的开始标签内可以指定使用的语言,可以通过使用 lang 属性指定,例如:lang=”jade”、lang=”ts”、lang=”sass”

2、全局配置与页面配置

3、数据绑定

五、实战项目

1、初始化云数据库

  • 在 uniCloud 下新建一个“db_init.json”文件,用于初始化云数据库
    在这里插入图片描述
  • 数据结构如下
{
    "集合名": {     // 集合名(表名)
        "data": [  // 数据
            {
                "键": "值",
                "键": "值"
            },
            {
                "键": "值",
                "键": "值"
            }
        ]
    }
}

2、将页面关联到 tabBar

  • 进入 pages.json 文件,添加 tabBar 字段
{
    "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
        {
            "path": "pages/tabbar/index/index",
            "style": {
                "navigationStyle":"custom",
                "navigationBarTextStyle":"white",
                "navigationBarTitleText":"首页"
            }
        }, 
        {
            "path": "pages/tabbar/follow/follow",
            "style": {
                "navigationBarTitleText":"关注"
            }

        }, 
        {
            "path": "pages/tabbar/my/my",
            "style": {
                "navigationBarTitleText":"个人中心"
            }
        }
    ],
    "globalStyle": { // 设置全局样式
        "navigationBarTextStyle": "black",
        "navigationBarTitleText": "uni-app",
        "navigationBarBackgroundColor": "#F07373",
        "backgroundColor": "#F8F8F8"
    },
    "tabBar": {  // 设置页面底部的 tabBar,至少2,最多5
        "color": "#666",  // 默认(未选择时)颜色
        "selectedColor": "#f07373",  // 选择时的颜色
        "backgroundColor": "#fff",  // tabBar 背景色
        "list": [{
            "pagePath": "pages/tabbar/index/index", // 页面路径
            "text": "首页",  // tabBar 文字
            "iconPath": "static/home.png",  // 未选中时 tabBar 图标
            "selectedIconPath": "static/home-active.png" // 选中时 tabBar 图标
        }, {
            "pagePath": "pages/tabbar/follow/follow", // 页面路径
            "text": "关注",  // tabBar 文字
            "iconPath": "static/follow.png",  // 未选中时 tabBar 图标
            "selectedIconPath": "static/follow-active.png"  // 选中时 tabBar 图标
        }, {
            "pagePath": "pages/tabbar/my/my", // 页面路径
            "text": "我的",  // tabBar 文字
            "iconPath": "static/my.png",  // 未选中时 tabBar 图标
            "selectedIconPath": "static/my-active.png"  // 选中时 tabBar 图标
        }]
    }
}

在这里插入图片描述

3、自定义导航栏

  • 每个页面存在原生导航栏,如果需要自定义,需要到 pages.json 进行配置
  • style 中设置 navigationStyle 的值为 custom
{
    "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
        {
            "path": "pages/tabbar/index/index",
            "style": {
                "navigationStyle":"custom",
                "navigationBarTextStyle":"white", // 只能设置 white/black 两种颜色
                "navigationBarTitleText":"首页"
            }
        }
    ]
}
  • 由于小程序有状态栏,所以需要使用条件编译设置状态栏的高度
<!-- 状态栏 -->
<!-- #ifndef MP-ALIPAY -->
<view :style="{height: statusBarHeight + 'px'}"></view>
<!-- #endif -->
<!-- 导航栏 -->

created() {
    // 获取手机系统信息
    const phoneInfo = uni.getSystemInfoSync()

    // 获得状态栏高度
    this.statusBarHeight = phoneInfo.statusBarHeight
    this.windowWidth = phoneInfo.windowWidth

    // #ifndef H5 || APP-PLUS || MP-ALIPAY
    // 获取胶囊的位置
    const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
    // console.log(menuButtonInfo)

    // 导航栏高度 = (胶囊底部高度 - 状态栏高度) + (胶囊顶部高度 - 状态栏高度)
    this.navbarHeight = (menuButtonInfo.bottom - phoneInfo.statusBarHeight) + (menuButtonInfo.top - phoneInfo.statusBarHeight)

    // 导航栏宽度
    this.windowWidth = menuButtonInfo.left
    // #endif

    // #ifdef MP-ALIPAY
    this.statusBarHeight = 0
    // #endif
},

4、使用字体图标

<uni-icons type="back" size="22" color="#fff"></uni-icons>

5、封装网络请求

在这里插入图片描述
- index.js

// 批量导出文件

const requireApi = require.context(
    // api 目录的相对路径
    '.',
    // 是否查询子目录
    false,
    // 查询文件的后缀
    /.js$/
)

let module = {}

requireApi.keys().forEach((key,index) => {
    if(key === './index.js') return

    Object.assign(module, requireApi(key))
})

export default module
  • list.js
import $http from '../http.js'

export const get_label = (data) => {
    return $http({
        url: 'get_label',
        data
    })
}

export const update_label = (data) => {
    return $http({
        url: 'update_label',
        data
    })
}
  • http.js
import store from '../store/index.js'

export default function $http(options) {
    const { url, data } = options

    const dataObj = {
        user_id: store.state.userInfo._id,
        ...data
    }

    return new Promise((resolve, reject) => {
        uniCloud.callFunction({
            name: url,
            data: dataObj
        }).then(res => {
            if(res.result.code === 200) {
                resolve(res.result)
            } else {
                reject(res.result)
            }
        }).catch(err => {
            reject(err)
        })
    })
}

6、点击选项卡实现切换内容

  • 点击变色:点击标签,触发事件,将当前点击的标签的索引赋值给 data 中的变量,然后绑定 class(:class=”{active: activeIndex === index}”),如果默认值与索引值相等,则激活变色样式
  • 切换内容:点击标签,触发事件,将当前点击标签的索引触发给调用该组件的页面,该页面得到索引值后根据索引获取标签名,然后再根据标签名查询得到对应的卡片内容,渲染到对应 swiper 内容块上
<template>
    <scroll-view class="tab-scroll" scroll-x >
        <view class="tab-scroll_box">
            <view class="tab-scroll_item" :class="{active: activeIndex === index}" v-for="(item,index) in list" :key="index" @click="clickTab(item,index)">{{item.name}}</view>
        </view>
    </scroll-view>
<template>

<script>
    data() {
        return {
            activeIndex: 0
        };
    },
    methods: {
        clickTab(item,index) {
            this.activeIndex = index
            this.$emit('tabClick', index)
        }
    }
</script>

<style>
.active {
    color: $lgk-base-color;
}
</style>

7、收藏的实现

  • 点击收藏按钮触发事件,将data中的变量值取反,并且更新数据库对应字段的值
<view class="icons" @click.stop="likeTab">
    <uni-icons :type="like?'heart-filled':'heart'" size="20" color="#f07373"></uni-icons>
</view>

data() {
    return {
        like: false
    };
},

methods: {
    likeTab() {
        this.like = !this.like
        this.setUpdateLikes()
    },
}

8、搜索逻辑实现

  • 首先使用 v-model 绑定搜索的值,并使用节流(延时器延时1秒)将输入的值绑定data中的变量,同时到数据库查询数据,只有点击查询得到的内容卡片,才会将输入的内容存储到 vuex 中,然后就可以通过引入并解构 mapState 得到搜索历史
import { mapState } from 'vuex'
computed: {
    ...mapState(['historyList'])
},
  • 在 vuex 中也会将搜索历史进行持久化
state: {
    historyList: uni.getStorageSync('__history') || []
},

9、标签页的实现逻辑

10、富文本渲染

11、评论内容实现逻辑

12、收藏与首页内容关联

13、关注与点赞

同步关注作者

14、反馈内容与图片上传

六、项目优化与平台兼容

七、项目打包与发布

总结