uniapp+vue3+vite+typescript架构下开发小程序
前言
这篇文章记录的是uniapp+vue3+vite+typeScipt架构下如何使用vue与ts开发。主要是1. vue的基本语法,2. uniapp在ts下的类型声明与使用,3.uniapp组件与API的使用,4.vue生态的使用,会使用pinia作为状态管理工具。
系列文章
前言
这篇文章记录的是uniapp+vue3+vite+typeScipt架构下如何使用vue与ts开发。主要是1. vue的基本语法,2. uniapp在ts下的类型声明与使用,3.uniapp组件与API的使用,4.vue生态的使用,会使用pinia作为状态管理工具。
uniapp与vue3结合开发
在uniapp中使用vue3开发,首先看到main.ts文件,这里有需要注意的地方是这里不是使用createApp来创建实例,而是使用createSSRApp来创建应用实例。然后导出了一个叫createApp的函数。我们可以在这里面写一些常用的操作。如注册全局变量,创建全局组件,注册插件等等。下面是我main.ts的代码片段
import { createSSRApp } from "vue"
import App from "./App.vue"
import Test from "@/component/Test/Test.vue"
import { createPinia } from "pinia"
export function createApp() {
const app = createSSRApp(App)
const pinia = createPinia() // 导入插件
app.config.globalProperties.$token = "xxxx" // 创建全局变量
app.component("Test", Test) // 注册全局组件
app.use(pinia)
return {
app
}
}
接下来新建一个demo文件,去实验vue的语法。我创建的名字叫vue.vue,这个文件可以自行去创建
- ref()与reactive()
这个应该是比较常用的api,写了一个增加数的按钮,很简单
- computed()
计算属性也是比较常用的api,写了一个count增加时+1的计算属性
- watch()与watchEffect()
这两个的区别我这里就不展开描述了,一大推文章,这里只贴用法
<template>
<div class="page_main">
<div>vue页面</div>
<Test />
<div class="add_button" @click="updateCount">点击</div>
<div>count值:{{ count }}</div>
<div>countPlus值: {{ countPlus }}</div>
<div>reactive: {{ obj.count }}</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, reactive, watch, watchEffect } from "vue"
const count = ref(0)
const obj = reactive({ count: 1 })
const countPlus = computed(() => count.value + 1)
watch(count, (newVal, oldVal) => {
console.log(newVal, oldVal)
})
const stop = watchEffect(() => {
console.log(`watchEffect`, count.value)
})
// stop() // 停止监听
const updateCount = () => {
count.value += 1
obj.count += 1
}
</script>
- 动态渲染与条件渲染
这里也很常规,直接使用v-for与v-if指令来
<tempalte>
<div v-for="(item, index) in list" :key="index" class="list_item">{{ item }}</div>
<div @click="changeTips">点击{{ tips.title }}</div>
<div v-if="tips.show === true">{{ tips.title }}</div>
</teamplate>
<script setup lang="ts">
const list = ref([1, 2, 3, 4, 5, 6])
const tips = reactive({
title: "展示",
show: false
})
const changeTips = () => {
tips.show = !tips.show
tips.title = tips.show === true ? "隐藏" : "展示"
}
</script>
- 动态class与style
和平常写vue的语法一样
<h3>动态class与style</h3>
<div :class="count === 2 ? 'active' : ''">count为2时变红</div>
<div :style="{ color: count === 2 ? 'red' : '' }">count为2时变红</div>
- 设置全局变量
定义全局变量是在main.ts中定义,我们来聚一个例子,在全局变量中记录token,并在页面上拿到这个token
//main.ts
export function createApp() {
const app = createSSRApp(App)
const pinia = createPinia() // 导入插件
app.config.globalProperties.$token = "xxxx" // 创建全局变量
app.component("Test", Test) // 注册全局组件
app.use(pinia)
return {
app
}
}
在页面中就这样使用
import { getCurrentInstance } from "vue"
const token = getCurrentInstance()?.appContext.config.globalProperties.$token
console.log(`token值`, token)
基本常用的语法我都尝试了一下,都是支持,所以可以放心的用。uniapp在vue3的支持这一块还是很nice的。
uniapp下ts的使用
简单记录一下在uniapp中使用ts的场景,因为自己写ts也不是很好,所以就按最常见的使用场景来记录一下
uniappAPI的TS声明
uniapp的类型定义是由@dcloudio/types 模块提供的,所以在使用uniapp+ts时请检查是否有这个包,如果没有需要下载。下载好后还需要在 tsconfig.json 文件中的 compilerOptions > types 部分配置。
泛型的使用
泛型是ts很常见的功能啦,这里简单写了一个print函数,使用了一下泛型
<script setup lang="ts">
type Print = <T>(data: T) => T
const print: Print = (data) => {
console.log(data)
return data
}
print("string") // 打印出string
print(10) // 打印出10
</script>
其他TS常用功能的使用
像基础的类型声明啥的都不说了,肯定是能正常使用的,还有一些类型断言,类型约束啥的也是可以使用,这里就不一一列举啦。ts这块应该没啥大坑,我就不再占用过多篇幅了。(主要是我经常用anyscript)
uniapp的组件与api使用
这里我来介绍开发中常用的功能进行记录。
跳转路由
跳转功能就正常的调uniapp提供的api就好,这里以navigateTo做代码示例
<template>
<div>uniapp+vue3+ts首页</div>
<div class="button" @click="navigateTo('/pages/vue/vue')">vue页面</div>
</template>
<script setup lang="ts">
const navigateTo = (url: string) => {
uni.navigateTo({
url: url
})
}
</script>
网络请求
网络请求也是最常用的api,使用uni.request(),这里也封装了一个uni.request()的工具方法。
我们先新建一个api文件夹,里面存放我们的api路径,这边适配这几种规则的接口信息
// api/index.ts
const Api: Record<keyof APIModule, string> = {
getUserInfo: "GET:user/info",
updateUserInfo: "POST:user/update",
getDetail: "GET: user/detail"
}
export { Api }
//声明文件
declare type APIModule = {
getUserInfo: {
url: string
params: {
test: string
}
response: {
code: number
data: {
id: string
name: string
age: number
} | null
msg: string | null
}
}
//这里就不全粘贴了,格式都是一样的
}
然后封装一个useApi的hook,这里有个坑就是success的回调参数有声明类型了,好像不太匹配,我就给注释掉检查啦,哈哈,如果有啥好的方法希望大家可以告诉我咋改,ts真心玩的不熟
import { Api } from "@/api/index"
import { BASE_URL } from "@/config/index"
function useApi<T extends keyof APIModule>(api: T) {
const [method, ...url] = Api[api].split(":")
const _method = method as "GET" | "POST"
const runAsync = (
params: APIModule[T]["params"],
header: object | null
): Promise<APIModule[T]["response"]> => {
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + url,
method: _method,
data: params,
header: Object.assign({}, header),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
success(res: APIModule[T]["response"]) {
if (res && res.code === 200) {
resolve(res)
} else {
reject(res)
}
},
fail(err) {
reject(err)
}
})
})
}
return {
runAsync
}
}
export { useApi }
数据缓存
使用的就是uni.setStorageSync,uni.getStorageSync,uni.removeStorageSync,uni.clearStorageSync()
uni.setStorageSync("test", "test")
const test = uni.getStorageSync("test")
其他api能力就不占篇幅举例啦,大家对着文档用,踩坑应该也是uni的已知的坑啦。
uniapp下vue生态的使用
这里我们使用vue新推出(其实已经不新啦)的pinia来举例。pinia是新推出的vue的状态管理库。这里不过多介绍pinia啦。有兴趣的可以看其他大佬的分享。这里直接上使用代码。
新建一个store文件夹,里面新建一个user.ts。里面创建了一个user
//store/index.ts
import { defineStore } from "pinia"
interface State {
count: number
}
export const useUserStore = defineStore("user", {
state: (): State => {
return {
count: 0
}
},
actions: {
updateName() {
this.count++
}
}
})
在pinia.vue中使用定义的store
<template>
<div></div>
</template>
<script setup lang="ts">
import { useUserStore } from "@/store/index"
import { storeToRefs } from "pinia"
const userStore = useUserStore()
const { count } = storeToRefs(userStore)
userStore.updateName()
console.log(`store`, count.value)
</script>
<style></style>
很简单的一个小demo,简单记录了如何使用pinia。
github地址
这个是这个demo的git地址uniapp_vue3_demo,分支是features/dev,有兴趣可以看一下完整的demo。
后记
以上就是我试用这个架构开发demo的一些记录。如果有新的更新我也会更新在这个系列。如果有什么问题或者讨论的点欢迎大佬们下方评论或者留言。
转载自:https://juejin.cn/post/7232164444985442364