uni-app D3实战(小兔仙)

216 阅读5分钟

1.pages.json和tabBar案例

1.1 文件介绍

image.png

1.2 做一下pages.json的路由和tabbar配置:

    {
      "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
        {
          "path": "pages/index/index",
          "style": {
            "navigationBarTitleText": "首页"
          }
        },
        {
          "path": "pages/my/my",
          "style": {
            "navigationBarTitleText": "我的"
          }
        }
      ],
      // 全局修改
      "globalStyle": {
        "navigationBarTextStyle": "white",
        "navigationBarTitleText": "uni-app",
        "navigationBarBackgroundColor": "#1bac9b",
        "backgroundColor": "#F8F8F8"
      },
      "tabBar": {
        // 修改选中时候的颜色
        "selectedColor": "#1bac9b",
        "list": [{
            "pagePath": "pages/index/index",
            "text": "首页",
            "iconPath": "/static/tabs/home_default.png",
            "selectedIconPath": "/static/tabs/home_selected.png"
          },
          {
            "pagePath": "pages/my/my",
            "text": "我的",
            "iconPath": "/static/tabs/user_default.png",
            "selectedIconPath": "/static/tabs/user_selected.png"
          }
        ]
      },
      "uniIdRouter": {}
    }

效果:

image.png

1.3总结和注意事项:

image.png

2. uni-app和原生小程序开发的区别

2.1 属性绑定的书写区别

2.2 事件绑定的区别

2.3 支持Vue常用指令

大致: image.png

2.4 轮播图案例

<template>
    <!-- 写结构: -->
    <swiper class="banner" indicator-dots :autoplay="false">
        <swiper-item v-for="item in pitures" :key="item.id">
            <!-- 以前是bindtap,现在@就好了(点击绑定自定义事件) -->
            <image @tap="onPreviewImage(item.URL)" :src="item.URL"></image>
        </swiper-item>
    </swiper>
</template>

<script>
export default {
    data() {
        return {
            title: 'Hello',
            pitures: [
                { id: '1', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_1.jpg' },
                { id: '2', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_2.jpg' },
                { id: '3', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_3.jpg' },
                { id: '4', URL: 'https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/uploads/goods_preview_4.jpg' }
            ]
        };
    },
    onLoad() {},
    methods: {
        onPreviewImage(URL) {
            // 测试绑定事件是否成功
            console.log(URL); //点击对应图片,成功在控制台输出图片url
            // 使用微信的官方预览方法
            // 定义一个形参v
            
            wx.previewImage({
            //或者可以写成uni.previewImage
                // 返回v中的url,将其提取到一个全新的数组里
                urls: this.pitures.map((v) => v.URL),
                current: URL
            });
        }
    }
};
</script>

<style>
.banner,
.banner image {
    width: 750rpx;
    height: 750rpx;
}
</style>

3.使用命令行创建uni-app项目

好处:不用依赖HBuilderX,可以在自己喜欢的编辑器上编辑(如cursor)

image.png

4. 使用vsCode开发uni-app项目

image.png

5. 正式开始实战

image.png 克隆命令: E:\DeskTop\XtxProject>git clone git.itcast.cn/heimaqiandu… heima-shop
结果:

image.png

6.1 基础架构-使用uni-ui组件库

使用easycom自动导入组件 image.png 使用easycom自动导入

image.png

image.png

6.2.使用uni-helper/uni-ui-types

官方并没有提供对应的类型说明文字,所以使用这个拓展包,用起来更加的方便和放心

image.png

image.png

6.3 总结:

image.png

7 状态管理(小程序端Pinia持久化)

回顾一下Pinia的作用:

image.png

image.png

image.png

image.png

image.png image.png

7.1 在小程序段使用persistent实现永久存储

因为网页端API和小程序端API有差异,所以我们干脆使用兼容多端的uni的API image.png

8 基础架构

image.png

8.1 数据交互-请求工具的封装

8.1.1 拦截器的封装

STRING:拦截器api的名称 object:拦截后的行为
拦截器拦截之后需要实现的四个核心业务: image.png 用户登录后获取token

8.1.2 请求函数的封装

image.png

8.1.2.1 http.ts文件中添加拦截器
// 添加拦截器
// 拦截request请求
// 拦截uploadFile文件上传

import { useMemberStore } from '@/stores';

// TODO;
// 非http开头需拼接地址
// 请求超时
// 添加小程序端请求头标识
// 添加token请求头标识

const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net';

// 添加拦截器
// 拦截request请求

const httpInterceptor = {
    // 拦截前触发
    // 注意:在ts项目中参数需要指定类型,所以要在形参options:后指定
    invoke(options: UniApp.RequestOptions) {
        // 1.非http开头的地址需要拼接地址,否则就是完整的
        options.url = baseURL + options.url;
        if (!options.url.startsWith('http')) {
        }
        // 2.请求超时,默认最大时间为60s(我们这改成10s)
        options.timeout = 10000;
        console.log(options);
        // 3.添加小程序端请求头标识
        options.header = {
            ...options.header,
            'source-client': 'miniapp'
        };
        // 4. 添加token请求头标识
        const meberStore = useMemberStore();
        const token = meberStore.profile?.token;
        if (token) {
            options.header.Authorization = token;
        }
        console.log(options);
    }
};

// ⭐ 必须导出一个函数给 main.ts 调用
export function setupInterceptor() {
    uni.addInterceptor('request', httpInterceptor);
    uni.addInterceptor('uploadFile', httpInterceptor);
}

8.1.2.2 在main.ts中注册拦截器

image.png

8.1.2.3 最终测试结果

image.png

8.1.3 封装Promis请求功函数

回顾一下promise和axios

image.png 回顾一下promise的固定两个参数

image.png image.png

8.1.3.2 成功resolve

// 请求函数
// @param UniApp.RequestOptions
// @return Promise

// TODO:
// 1.返回Promisre对象
// 2.请求成功
//   2.1提取核心数据 res.data
//   2.2 添加类型,支持泛型

// 3.请求失败
//     3.1网络错误->提示用户换网络
//     3.2 401错误->清理用户信息,跳转到登录页
//     3.3 其他错误->根据后端错误信息轻提示

interface Data<T> {
    code: string;
    msg: string;
    // 因为result的长度不固定,所以给她使用泛型
    result: T;
}

// 实现请求函数的封装并返回一个对象
export const http = <T>(options: UniApp.RequestOptions) => {
    // 返回一个Promis对象
    return new Promise<Data<T>>((resolve, reject) => {
        uni.request({
            ...options,
            // 2.请求成功
            success(res) {
                // 2.1提取核心数据(as Data<T>类型断言)
                // 数据断言:简单来说,就是覆盖 TS 自动类型推断。
                resolve(res.data as Data<T>);
            }
        });
    });
};

image.png

8.1.3.4 失败reject

image.png

image.png 实现代码:


// 请求函数
// @param UniApp.RequestOptions
// @return Promise

// TODO:
// 1.返回Promisre对象
// 2.请求成功
//   2.1提取核心数据 res.data
//   2.2 添加类型,支持泛型

// 3.请求失败
//     3.1网络错误->提示用户换网络
//     3.2 401错误->清理用户信息,跳转到登录页
//     3.3 其他错误->根据后端错误信息轻提示

interface Data<T> {
    code: string;
    msg: string;
    // 因为result的长度不固定,所以给她使用泛型
    result: T;
}

// 实现请求函数的封装并返回一个对象
export const http = <T>(options: UniApp.RequestOptions) => {
    // 返回一个Promis对象
    return new Promise<Data<T>>((resolve, reject) => {
        uni.request({
            ...options,
            // 2.请求成功
            success(res) {
                // 通过状态码查看是否成功
                if (res.statusCode >= 200 && res.statusCode < 300) {
                    // 2.1提取核心数据(as Data<T>类型断言)
                    // 数据断言:简单来说,就是覆盖 TS 自动类型推断。
                    resolve(res.data as Data<T>);
                }
                // 3.2 401错误->清理用户信息,跳转到登录页
                else if (res.statusCode === 401) {
                    const memberStore = useMemberStore();
                    // 清理数据
                    memberStore.clearProfile();
                    // 跳转到登录页
                    uni.navigateTo({
                        url: '/pages/login/login'
                    });
                    // uni.redirectTo({ url: '/pages/login/login' });
                    reject(res);
                } else {
                    // 3.3 其他错误->根据后端错误信息轻提示
                    uni.showToast({
                        icon: 'none',
                        title: (res.data as Data<T>).msg || '请求错误'
                    });
                    // 标记为失败
                    reject(res);
                }
            },
            // 响应失败(用户网络有误)
            fail(err) {
                // 轻提示
                uni.showToast({
                    icon: 'none',
                    title: '网络错误,换个网络试试吧!'
                });
                reject(err);
            }
        });
    });
};

9 自定义导航栏

image.png

9.1 安全区域

使用uni的getSystemInfoSync()的api来实现不同机型自动适配的安全区域 image.png

image.png 结果: iphone6:

image.png iphone15pro:

image.png