uniapp产品
uni-app
是一个DCloud出品的、
使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。DCloud另一个有名的产品是HBuilderX。
根据官网顶部的tab,我们可以发现DCloud的产品包括
uni-app、uni-app x、uniCloud、HBuilder、uni 小程序 sdk。HBuilder自不必说,它是一款ide。uni 小程序 sdk是为原生打造的、可运行基于 uni-app 开发的小程序前端项目的框架,从而帮助原生App快速获取小程序的能力。uniCloud则提供了类似微信云开发的能力,只不过是微信云和阿里云提供了实际的云服务,uniCloud则做了一个适配层。
作为前端开发部分,我们更多的是使用uni-app或者uni-app x。这两者有什么区别呢?根本的区别是渲染引擎不同,uni-app是基于webview渲染的,而uni-app x是基于原生渲染的。
uni-app | uni-app x | |
渲染引擎 | webview | 原生 |
开发语言 | js,ts | uts |
界面框架 | vue | uvue |
css | 完整的css | 受限的css |
当然uni-app也不仅仅是只有webview渲染,依靠weex的能力,它也实现了类似RN的原生渲染能力。
界面框架 | vue | nvue |
渲染引擎 | webview | 改进的weex |
css | 完整的css | 受限的css |
api | 比较丰富 | 比较有限 |
性能 | 一般 | 较好 |
接下来再看看各框架的组件和api支持情况:
uniapp h5 | uniapp小程序 | uniapp 原生nvue | uniapp 原生 | uniapp x h5 | uniapp x app | |
内置基础组件 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
基于内置的自定义组件 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
原生ui嵌入 | - | - | nvue组件 | - | - | uts组件插件 |
标准API | ✅ | ✅ | 部分不支持,用nvue api替代 | ✅ | ✅ | ✅ |
语言相关 | ECMAScript | ECMAScript | ECMAScript | ECMAScript | uts api | uts api |
h5+ api | - | - | ✅ | ✅ | - | - |
native.js | - | - | ✅ | ✅ | - | - |
使用UI组件库
uni-app支持的组件分为vue组件和小程序自定义组件。vue组件分为内置组件、扩展组件uni-ui以及第三方组件。小程序自定义组件:其规范不是vue规范,而是小程序规范。
扩展组件有很多概念,比如easycom规范、uni_module
、datacom
、原生组件
、uniCloud组件
。详见:组件使用的入门教程 | uni-app官网
uni-app的插件市场,有很多扩展组件,有的是单独的,有的是成套的。 uni ui是DCloud官方出了一套扩展组件,这些扩展组件支持单个组件从插件市场下载,也支持npm引入uni ui,当然更方便的是在HBuilderX新建项目时直接选择uni ui项目模板。npm安装请参考:
uni-app官网
插件市场,https://ext.dcloud.net.cn,有各种玲琅满目的组件、模板。 其中成套的全端兼容ui库包括:
uViewUI:整合了非常多组件,功能丰富、文档清晰,但不支持nvue(2.x已支持nvue)。但是不支持vue3。uv-ui支持vue2+3。
colorUI css库:颜值很高,css库而非组件。
unify UI:全端支持的组件库,侧重nvue(商城已下架)
mypUI:全端支持的组件库,侧重nvue
ThorUI组件库
graceUI商业库
使用TypeScript
1.安装类型声明文件
pnpm i -D @dcloudio/types @uni-helper/uni-ui-types @uni-helper/uni-app-types
2.配置类型声明文件
// tsconfig.json
{
"compilerOptions": {
// ...
"types": [
"@dcloudio/types", // uni-app API 类型
//"miniprogram-api-typings", // 原生微信小程序类型
"@uni-helper/uni-app-types", // uni-app 组件类型
"@uni-helper/uni-ui-types" // uni-ui 组件类型
]
},
// vue 编译器类型,校验标签类型
"vueCompilerOptions": {
"nativeTags": ["block", "component", "template", "slot"]
}
}
实战
这里我们实现一个基础的登录页面:
代码如下:
<template>
<view class="app">
<uni-popup ref="popup" type="message">
<uni-popup-message type="error" :message="message" :duration="1000"></uni-popup-message>
</uni-popup>
<view class="logo">
<image src="../../static/logo.png"></image>
</view>
<uni-segmented-control class="segments" :current="currentIndex" :values="items" @clickItem="onClickItem"
styleType="button" activeColor="#07c160" inActiveColor="white"></uni-segmented-control>
<!-- <view class="segments">
<view :class="['segment', {'selected':accountType == 1}]" @click="onTapSegment" data-type="1">我是学生</view>
<view :class="['segment', {'selected':accountType == 2}]" @click="onTapSegment" data-type="2">我是教师</view>
<view :class="['segment', {'selected':accountType == 3}]" @click="onTapSegment" data-type="3">我是教务</view>
</view> -->
<view class="page__bd">
<uni-forms ref="form" :modelValue="formData" :rules="rules">
<uni-forms-item label="账号" name="account">
<uni-easyinput type="text" v-model="formData.account" placeholder="请输入账号" />
</uni-forms-item>
<uni-forms-item label="姓名" name="name">
<uni-easyinput type="text" v-model="formData.name" placeholder="请输入姓名" />
</uni-forms-item>
<uni-forms-item label="密码" name="password">
<uni-easyinput type="password" v-model="formData.password" placeholder="请输入密码" />
</uni-forms-item>
</uni-forms>
</view>
<view class="weui-btn-area">
<button class="weui-btn" type="primary" @click="submitForm">登录</button>
</view>
</view>
</template>
<script lang="ts" setup>
import type { UniForms, UniPopup, UniSegmentedControlOnClickItemEvent } from '@uni-helper/uni-ui-types';
import { reactive, ref } from 'vue';
const popup = ref<UniPopup | null>(null)
const form = ref<UniForms | null>(null)
const rules = ref({
account: {
rules: [{
required: true,
errorMessage: '请输入账号',
}]
},
name: {
rules: [{
required: false,
errorMessage: '请输入姓名',
}]
},
password: {
rules: [{
required: true,
errorMessage: '请输入密码',
}]
},
})
type LoginParams = {
account : string,
name? : string,
password : string
}
const formData = reactive<LoginParams>({
account: "",
password: ""
})
const message = ref<string>("")
const submitForm = () => {
form.value?.validate().then((res : LoginParams) => {
console.log(res)
message.value = "错误"
popup.value?.open()
}).catch((error : any) => {
console.log(error)
})
}
const items = ['我是学生', '我是教师', '我是教务']
const currentIndex = ref(0)
const onClickItem = (e : UniSegmentedControlOnClickItemEvent) => {
if (currentIndex.value != e.currentIndex) {
currentIndex.value = e.currentIndex
}
}
// const accountType = ref(1)
// const onTapSegment = (e:UniHelper.BaseEvent)=>{
// const { type } = e.currentTarget?.dataset!
// accountType.value = parseInt(type)
// console.log(e)
// }
</script>
<style>
.app {
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 40rpx 40rpx;
}
.logo image {
width: 300rpx;
height: 300rpx;
}
.segments {
width: 500rpx;
margin-top: 70rpx;
}
/* .segments {
display: flex;
}
.segment {
padding: 10rpx 38rpx;
border: 2rpx solid #eee;
background-color: #fff;
}
.segment.selected {
color: #fff;
background-color: #07c160;
} */
.page__bd {
margin-top: 40rpx;
}
</style>
注释掉的代码里我们自己实现了一个segmented control。这里要注意的一点是@onClick的参数类型是UniHelper.BaseEvent,花了很多时间,也没有在官方文档上找到相关说明,只是根据打印的数据结构,然后在对应的类型文件中,找到了这个看起来对的类型。另外这里用到了内置的segmented control,据文档所示,存在一个inActiveColor属性,设置后发现不生效,查看源码才发现根本就没有这个属性。uni ui看起来不是一个被精心设计、实现的组件库,目前有比较多的问题被反馈。HBuilderX也存在偶尔会乱报错误的问题,而且不显示错误的原因。
uniapp总体而言,是一个理念和商业化比较成功的产品,但是还是有诸多瑕疵,建议少点自嗨,多花点心思打磨产品和代码。