/**
* @author wn
* @date 2023/07/26 10:14:15
* @description:uniapp 笔记
*/
/*
1 安全区域
屏幕去掉 状态栏 +刘海 剩余展示内容的区域 --
可通过 uni.getSystemInfoSync() 获取屏幕 上边界 到安全区 顶部 的距离。
safeAreaInsets = {top: 59, left: 0, right: 0, bottom: 34}
"navigationStyle": "custom", // 隐藏默认导航,自定义
页面 直接顶到 windows 最上方
这时 paddingTop:安全距离
view 中的 内容就不会被遮挡
const { safeAreaInsets } = uni.getSystemInfoSync()
const top = ref<number | undefined>()
top.value = safeAreaInsets?.top
:style="{ paddingTop: top + 'px' }"
自定义状态栏 返回按钮 --可以使用 navigator + icon 自定义图标
open-type="navigateBack" 对应 uni.navigateBack 设置 路由
2 icon 使用 iconFont
3 font-size 有继承size时 可以指定 百分比
font-size: 80%;
4 伪元素 可以通过 display:flex; 与 text的内容 排列
.caption {
display: flex;
justify-content: center;
align-items: center;
&::before,
&::after {
content: '';
width: 20rpx;
height: 20rpx;
background: url(@/static/images/bubble.png) center/contain;
}
}
5 uniAPP css 使用 标签选择器 报警告 要避免
6 v-if 导致 setup 执行了两次
v-show 不会 onMounted中也不会
7 注意 page { height: 100%; }
基于 scroll-view 组件实现 下拉刷新 上拉加载
配置 refresher-enabled 属性,开启自定义下拉刷新交互
监听 @refresherrefresh 事件,判断用户是否执行了下拉操作
配置 refresher-triggered 属性,是否关闭下拉状态 true 开始动画 false 关闭动画
配置 @scrolltolower 滚动到底部/右边,会触发 事件 -- 上拉加载
8 生成骨架屏
微信开发者工具 --左边页面 右下角--三个点--生成骨架屏
--xxx.skeleton.wxml 和 xxx.skeleton.wxss--
将二者封装成 xxx.skeleton.vue组件 这里生成的是整个页面的骨架屏
要是只需要部分 比如 navBar 不需要 template 中 删除 结构即可
<XXXSkeleton v-if="isLoading" />
<template v-else>
<xxx1.vue />
<xxx2.vue />
</template>
9 navigator 参数传递
navigator 通过url传递的参数 会在 page 的 props中接收到
传递的参数应该是基本类型(如字符串、数字等),或者是经过JSON序列化的对象
<navigator
:url="'/pages/navigate/navigate?item='+ encodeURIComponent(JSON.stringify(item))">
const { item } = defineProps<{ item:string }>()
const obj = JSON.parse(decodeURIComponent(item))
自定义状态栏
10 小程序的 tap 事件 等同于 click
11 setup 的执行时机 在 onLoad 之前
setup > onLoad > beforeCreated
12 uni-popup 弹出层组件
插入内容 uni-popup-message uni-popup-dialog uni-popup-share
uni-popup 组件实例 通过 open close 打开与关闭
const popupRef = ref<{
open: (type?: UniHelper.UniPopupType) => void
close: () => void
}>()
popup.value?.open("top")
popup.value?.close()
禁止滚动穿透
13 微信登录 获取微信用户基本信息(昵称、性别、手机号码等)
用户在使用小程序时,其实已登录微信,其本质上就是:微信授权给小程序读取微信用户信息
1 前端:调用 wx.login() 接口获取登录凭证(code)
后端:通过凭证(code)向微信服务器生成 用户登录态
用户登录态,不包含用户昵称、性别、手机号码等信息,作用是用于后端与微信服务器通讯
onLoad-->
const { code } = await wx.login()
2 微信登录接口(后台 API)
button -- open-type="getPhoneNumber"
点击 弹窗--允许后
触发 @getphonenumber 回调中 获取 -- LoginParams
type LoginParams = {
code: string
encryptedData: string
iv: string
}
回调中 -- 调用 后台 API -- 获取 -- LoginResult
export type LoginResult = {
id: number // 用户ID
avatar: string // 头像
account: string // 账户名
nickname?: string // 昵称
mobile: string // 手机号
token: string // 登录凭证
}
14 pages.json -- "navigationBarTextStyle": "white"
导航栏标题-文字颜色 还可以设置当前页面 状态栏 电池,时间等文字颜色
仅支持 black/white
15 分包 1 按模块管理页面,方便项目维护。
2 减少主包体积,用到的时候再加载分包,属于性能优化解决方案
通过 插件 uni-create-view 可以快速新建分包页面,自动配置分包路由。
注意: 自动生成的分包页面 需要修改下 分包加载规则 的 路径
subPackages--[]
分包预下载 -- preloadRule
当用户进入【某个】页面时,由框架自动预下载 分包,提升进入后续分包页面时的启动速度
16 表单校验 -- uni-forms -- uni-forms-item
1 表单校验 2 自定义校验规则 3 动态表单校验 -- v-model的巧妙赋值 (name:value)
触发时机 validate-trigger= "bind" -- 数据改变时
blur--input失去焦点 submit 提交数据时
17 滑动删除 uni-swipe-action--uni-swipe-action-item
可以通过 1 数据 2 插槽 -- 生成 左右滑块内容
点击滑块触发 click 事件 -- 只对1数据渲染生效
2插槽渲染的 通过插槽自身的点击事件触发 @tap
滑块 开关 触发 change 事件
18 SKU 组件 -- gitee 中 源码中 components--下载 导入自己项目中 components
组件市场 下载 组件 按照文档使用
<vk-data-goods-sku-popup
ref="skuPopup"
v-model="skuKey" true为打开组件,false为关闭组件
border-radius="20" 顶部圆角值
:localdata="goodsInfo" 数据源
:mode="skuMode" 1:都显示 2:只显示购物车 3:只显示立即购买
@open="onOpenSkuPopup" 打开组件时
@close="SkuPopup" 关闭组件时
@add-cart="addCart" 加到购物车时--选完SKU才会触发 selectShop 当前选择的sku数据
@buy-now="buyNow" 立即购买时--选完SKU才会触发 selectShop 当前选择的sku数据
></vk-data-goods-sku-popup>
还可以通过 属性 配置
最大最小购买数量 点击步长 库存显隐 主题 右上角关闭按钮及样式 立即购买与加入购物车 文字内容 样式 背景
商品缩略图背景 按钮可点不可点 样式
localdata -- 数据格式
数据定义重点看
(sku_list--sku_name_arr) --> (spec_list)
{
"_id":"001", // 商品ID
"name": "iphone11", // 商品名称
"goods_thumb":"", // 商品头像
// 该商品对应的sku列表 -- 也就是最终的 选完规格后的 库存商品
"sku_list": [
{
"_id": "001", // SKU ID
"goods_id": "001", // 商品ID
"goods_name": "xx", // 商品名称
"image": "" // SKU头像
"price": 19800, // SKU 价格
"stock": 100 // 库存
// 该SKU由哪些规格组成(规格是有顺序的,需要与spec_list的数组顺序对应)
"sku_name_arr": ["红色", "128G", "公开版"],
}
],
// 商品规格列表
"spec_list": [
{
"name": "颜色", // 第一组规格名
// 第一组规格的 第一项规格值名称 二项规格值名称 三项规格值名称
"list": [{"name": "红色"},{"name": "黑色"},{"name": "白色"}]
},
{
"name": "内存",
"list": [{"name": "128G"},{"name": "256G"}]
},
{
"name": "版本",
"list": [{"name": "公开版"},{"name": "非公开版"}]
}
]
}
sku_name_arr 数组的第一个值sku_name_arr[0] = spec_list[0].list中的任意一个元素的name属性的值
spec_list[0].list中必须要有且只有一个元素的name属性的值为"红色"
19 组件类型生命
1 自定义组件 -- custom.vue
2 组件类型 -- import custom from '@/components/custom.vue'
typeof custom
3 组件实例 -- InstanceType<typeof custom>
方式二
1 import type { Component } from '@uni-helper/uni-app-types'
2 定义 props -- interface CustomProps {
name:string
}
3 Component<T> 等同于 typeof T
Component<CustomProps> === typeof custom
4 组件实例 -- InstanceType<Component<CustomProps>>
最后 -- 全局组件类型声明--这样自定义的组件就有类型了
declare module 'vue' {
export interface GlobalComponents {
'custom': typeof custom
'custom2': Component<CustomProps>
}
}
20 滚动驱动的动画 -- this.animate(selector, keyframes, duration, ScrollTimeline)
this.animate(
'.avatar', // 选择器 多个空格隔开
[{
borderRadius: '0',
borderColor: 'red',
transform: 'scale(1) translateY(-20px)',
offset: 0,
}, {
borderRadius: '25%',
borderColor: 'blue',
transform: 'scale(.65) translateY(-20px)',
offset: .5,
}],
2000,
{
scrollSource: '#scroller', // 以谁滚动触发动画
timeRange: 2000,
startScrollOffset: 0,
endScrollOffset: 85,
})
纯 CSS 实现
21 开发环境 -- boolean
import.meta.env.DEV 开发
import.meta.env.PROD 发布
22 微信支付 -- 获取微信支付参数 + 发起微信支付
const onOrderPay = async () => {
// 开发环境 DEV
if (import.meta.env.DEV) {
// 开发环境 -- 模拟支付
await getPayMockApi({ orderId: id })
} else {
// 正式环境支付 -- 1.获取支付订单信息,
const res = await getWxPayApi({ orderId: id })
// uni.requestPayment(res) -- res:UniApp.RequestPaymentOptions
// 2.调用微信支付API -- 弹框输密码
await wx.requestPayment(res)
}
*/
===========================项目打包============================
======微信小程序端========
1 运行打包命令 pnpm build:mp-weixin -- vsCode
2 预览和测试,微信开发者工具导入生成的 /dist/build/mp-weixin 目录 -- 微信开发者工具
3 上传小程序代码 -- 微信开发者工具 -- 上传
4 提交审核和发布 -- 微信公众平台 -- 版本管理 -- 提交审核
打包成其他小程序端的步骤类似,只是更换了 打包命令 和 开发者工具 。
=======H5 端============
1 运行打包命令 pnpm build:h5 -- vsCode
2 预览和测试,使用浏览器打开 /dist/build/h5 目录下的 index.html 文件
3 由运维部署到服务器
// manifest.json
{
// 网页端特有配置
"h5": {
"router": {
"base": "./" // 基础路径:./ 为相对路径
}
}
}
======打包为 APP 端=======
HBuilderX
1 手机预览与调试
2 导入HBuilderX-->选中项目根目录-->运行(运行到手机或模拟器)-->下载真机运行插件-->运行到Android App基座
打包APP -- 云打包
1 Manifest 中 获取 DCloud AppId
2 发行(原生APP 云打包)-->注册 DCloud 账号--> 登陆 DCloud-->
3 发行(原生APP 云打包)
使用云端证书(详情中 DCloud AppId -- 获取证书 -- Android 云端证书--创建证书)
正式打包
传统打包 或者 快速安心打包
打包
安装云打包插件
打包
======打包为 IOS 端=======
HBuilderX + MacBook + iphone
1 手机预览与调试
2 导入HBuilderX-->选中项目根目录-->运行(运行到手机或模拟器)-->运行到 IOS App基座
建议运行到模拟器上 真机版本太多了
mac 安装 Xcode 提供 iPhone 模拟器
运行 到 IOS App基座 时就会有 多个版本的 模拟器
打包IOS -- 云打包
需要 ios IDP/IEP 证书 -- 申请 每年几百元
证书私钥密码
证书profile文件
私钥证书
花钱就有了
其他按步骤进行填写
正式打包
传统打包 或者 快速安心打包
打包
====================================
各平台兼容
1 小程序端 不支持 * 选择器
运行直接报错 --> 并集选择器 view,text,image{ }
2 页面视口差异 page
H5端 -- 整个页面都是 视口 (上下 通过定位画出)
小程序端 + APP端 -- 顶部导航栏 + 视口(webview区域) + 底部 tabBar
(非tabBar页 或 者自定义导航栏 -->视口webview区域会相应延伸)
A 视口内容 -- 是否 会被 上下 遮挡 (H5端)
page {
height: 100% !important;
}
因为内部的继承关系 100% 可以让 H5的视口--page 在 中间,不会被上下部分因为定位遮挡
B 定位 组件的位置 -- 是否 会被 上下 遮挡 (H5端)
--window-bottom App 小程序 都是 0 ,H5 tabBar高度
--window-top App 小程序 都是 0 ,H5 导航栏高度
position:fixed;
bottom:var(--window-bottom);
3 H5 style 默认开启 scoped
开发者工具生成的 骨架屏 是根据页面样式 + 其他样式生成的
打包到 H5 或者 APP 后
因为 默认开启了 scoped
骨架屏 依赖的 一些组件样式 比如 首页(轮播图,分类,猜你喜欢) 的样式引用不到
骨架屏 样式 异常
将 scss 写到独立的 category.scss ,hot.scss 中
组件 和 骨架屏 style 中 分别引用
骨架屏中
#ifdef H5 || APP-PLUS
@import '../styles/category.scss';
@import '../styles/hot.scss';
#endif
4 组件兼容
编译到不同的平台时 相同的组件可能会 编译成 不同的 组件树
例如 navigator --> a
标签 与 结构 父子嵌套 都会变化 --导致样式 失效 -- flex失效 类名丢失 等
根据平台 通过条件编译调整 css 样式 即可
5 js 的 跨端 条件编译 -- 根据文档查阅即可
微信支付
选择图片