从vue3到uniapp,快速上手,基础全掌握

毕设课才讲的uniapp,不够详细且进度太慢。

为了照顾其他同学,赶出了这篇文章,细节后面再补充。如果有误,欢迎指正;觉得不错,欢迎点赞。


uni-app 介绍

  • uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。你可以理解uniapp为一个vue的组件库,经过封装可以适用多个平台。
  • 本文旨在让拥有vue基础的同学快速上手uniapp,如果没有uniapp基础,请移步我的vue笔记
  • uniapp很多东西与vue一样,本文只介绍不同之处。
  • 官网:https://uniapp.dcloud.net.cn

准备工具

  • Hbuilderx (开发与编译工具)
  • 微信小程序开发工具(微信小程序预览测试)
  • vscode (如果使用命令行开发)
  • nodejs

新建项目 / 认识界面

HBuilderX 创建 uni-app 项目

1.下载安装 HbuilderX 编辑器

2.通过 HbuilderX 创建 uni-app vue3 项目

3.安装 uni-app vue3 编译器插件

4.编译成微信小程序端代码

5.开启服务端口

小技巧分享:模拟器窗口分离和置顶

HBuildeX 和 微信开发者工具 关系

除了运行在微信开发者工具,实际开发中更多是运行在浏览器,只有完成一些模块的开发才在其他平台运行。因为uniapp编译到其他平台有延时,没有h5快。

命令行创建 uni-app 项目

通过命令行创建 uni-app 项目,不必依赖 HBuilderX,TypeScript 类型支持友好。

命令行创建 uni-app 项目:

vue3 + ts 版

# 通过 git 从 gitee 克隆下载
git clone -b vite-ts https://gitee.com/dcloud/uni-preset-vue.git

创建其他版本可查看:uni-app 官网

运行方法:

pnpm run dev:h5 # 以h5运行
pnpm run dev:mp-weixin #打包为微信小程序

如果打包为微信小程序,需要在微信开发者工具中导入dist目录下的mp-weixin

转换为命令行结构

官方插件市场不好用,还有广告,所以我拒绝

拉取命令行项目:

git clone -b vite-ts https://gitee.com/dcloud/uni-preset-vue.git

将使用HbuilderX创建的项目全部移动到src目录下面:

使用vscode或idea等打开项目(HubilderX buhaoyong),运行下面命令:

现在的运行方法:

将项目导入vscode或idea等工具,运行下面命令:

# 安装依赖
pnpm i
# 运行项目
pnpm dev:h5

然后,你可以在uniapp项目使用element plus(根据官方文档配置后):

效果:

vscode插件

如果使用vscode开发,还需要安装下面插件:

内置组件

  • 为了实现多端的兼容,uniapp将html原生标签封装为内置组件,可以在多端显示一致的效果
  • 因此,不要在uniapp开发中使用html元素标签,例如h3,div,span等,而是使用uniapp内置组件

uniapp常用内置组件如下:

  • view :类似于div,用于包裹各种元素内容。
  • text : 类似span
  • button : 按钮
  • form :表单
  • input : 输入框
  • navigator :超连接,但是只能跳转到在page.json注册了的页面
  • image : 图片

更多内置组件查看官方文档

示例:

<template>
  <view>
    <template v-if="test">
      <view>test 为 true 时显示</view>
    </template>
    <template v-else>
      <view>test 为 false 时显示</view>
    </template>
  </view>
</template>
<script setup>
  import {ref} from 'vue'
  const test = ref(true)
</script> 

目录结构

使用HbuilderX创建的工程的结构一般如下(没有package.json,不能通过npm安装依赖):

使用命令行创建的uniapp项目结构一般如下:

即使用vite创建vue工程,并将HBuilder创建的工程移动到src中

对uniapp文件的介绍:

├─pages            业务页面文件存放的目录
│  └─index
│     └─index.vue  index页面
├─static           存放应用引用的本地静态资源的目录(注意:静态资源只能存放于此)
├─unpackage        非工程代码,一般存放运行或发行的编译结果
├─index.html       H5端页面
├─main.js          Vue初始化入口文件
├─App.vue          配置App全局样式、监听应用生命周期
├─pages.json       **配置页面路由、导航栏、tabBar等页面类信息**
├─manifest.json    **配置appid**、应用名称、logo、版本等打包信息
└─uni.scss         uni-app内置的常用样式变量

page.json

页面和路由

  • 在uniapp中,我们不再需要使用Vue Router进行路由管理,而是直接在page.json中进行路由配置。
  • 创建页面:在page页面下,创建 页面名/页面名,然后在page.json中注册 (HbuilderX自动完成)
  • toptar为官方实现的路由跳转组件,点击对应图标就会自动跳转到对应页面

{
  // 页面路由
  "pages": [
    {
      "path": "pages/index/index",
      // 页面样式配置
      "style": {
        "navigationBarTitleText": "首页"
      }
    },
    {
      "path": "pages/my/my",
      "style": {
        "navigationBarTitleText": "我的"
      }
    }
  ],
  // 全局样式配置
  "globalStyle": {
    "navigationBarTextStyle": "white",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#27BA9B",
    "backgroundColor": "#F8F8F8"
  },
  // tabBar 配置
  "tabBar": {
    "selectedColor": "#27BA9B",
    "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"
      }
    ]
  }
}

效果:

组件自动导入

通过配置page.json的easycom属性,可以自动导入组件(包括自定义组件和第三方组件库)

安装 uni-ui 组件库 (HbuilderX创建不用安装,而是在官方插件市场下载)

pnpm i @dcloudio/uni-ui

配置自动导入组件

// pages.json
{
  // 组件自动导入
  "easycom": {
    "autoscan": true,
    "custom": {
      // 导入官方组件库:uni-ui 规则如下配置  
      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" ,
       // 导入自定义全局组件:以 XF 开头的组件,在 components 目录中查找
      "^XF(.*)": "@/components/XF$1.vue"
    }
  },
  "pages": [
    // …省略
  ]
}

安全区域

不同手机的安全区域不同,适配安全区域能防止页面重要内容被遮挡。

可通过 uni.getSystemInfoSync() 获取屏幕边界到安全区的距离。

自定义导航配置

// src/pages.json
{
  "path": "pages/index/index",
  "style": {
    "navigationStyle": "custom", // 隐藏默认导航
    "navigationBarTextStyle": "white",
    "navigationBarTitleText": "首页"
  }
}

组件安全区适配

<!-- src/pages/index/componets/CustomNavbar.vue -->
<script>
  // 获取屏幕边界到安全区域距离
  const { safeAreaInsets } = uni.getSystemInfoSync()
</script>

<template>
  <!-- 顶部占位 -->
  <view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
    <!-- ...省略 -->
  </view>
</template>

页面传值

		<navigator 		
		:url="'/pages/classlist/classlist?id='+item._id+'&name='+item.name" 
		class="box" >
		</navigator>

上面代码中的navigator可以通过Query 参数传值

使用uniapp的onload函数即可获取

import {onLoad} from "@dcloudio/uni-app"

onLoad((e )=>{	
  let {id,name} = e 
  console.log(id,name);
})

状态管理

使用hbuilder创建的项目自带pinia,无需安装

使用命令行创建,需要自己安装

pinia-plugin-persistedstate会报错,我们使用pinia-plugin-unistorage替代

# 安装pinia
pnpm i pinia

# 安装pinia持久化存储插件
pnpm i pinia-plugin-unistorage

创建pinia实例(stores/index.ts)

import { createPinia } from 'pinia'
import { createUnistorage } from 'pinia-plugin-unistorage'

// 创建 pinia 实例
const pinia = createPinia()
// 持久化
pinia.use(createUnistorage())

// 默认导出,给 main.ts 使用
export default pinia

在main.js/ts中引入pinia

import App from './App'

import { createSSRApp } from 'vue'
import pinia from './stores'

export function createApp() {
    const app = createSSRApp(App)
    const pinia = createPinia()
    app.use(pinia)
    return {
        app,
    }
}

基本示例:

// stores/modules/counter.ts
import { defineStore } from 'pinia';
 
export const useCounterStore = defineStore('counter', {
	state: () => {
		return { count: 0 };
	},
	// 也可以这样定义
	// state: () => ({ count: 0 })
	actions: {
		increment() {
			this.count++;
		},
	},
});

<template>
  <view class="content">
    <text>{{ counterStore.count }}</text>
      <button @click="counterStore.increment">+1</button>
  </view>
</template>

<script setup lang="ts">
import { useCounterStore } from '@/stores/modules/counter';
const counterStore = useCounterStore()
</script>

pinia持久化实例

组合式写法:

import { defineStore } from 'pinia';
 
export const useCounterStore = defineStore('counter', {
   unistorage: true, // 开启持久化
	state: () => {
		return { count: 0 };
	},
	actions: {
		increment() {
			this.count++;
		},
	},
});

组合式写法:

import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useCounterStore = defineStore('counter', 
  () => {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    return {
      count,
      increment,
    };
  },{
    unistorage: true,
  }
);

stores/index.ts统一导出

//...

// 模块统一导出
export * from './modules/couter'

封装http请求

使用hbuilder创建的项目自带axios,无需安装

使用命令行创建,需要自己安装

pnpm i axios

封装本地存储:

//utils/auth.js
const TokenKey = 'xxx'

export function getToken() {
	return uni.getStorageSync(TokenKey)
}

export function setToken(token) {
	return uni.setStorageSync(TokenKey, token)
}

export function removeToken() {
	return uni.removeStorageSync(TokenKey)
}

封装实例:

//utils/request.js
import {
	getToken
} from '@/utils/auth.js'

// 全局请求封装
const base_url = 'http://localhost:8080';
// 请求超出时间
const timeout = 5000;

// 需要修改token,和根据实际修改请求头
export const request = (params) => {
	let url = params.url;
	let method = params.method || "get";
	let data = params.data || {};
	let header = {
		'Authorization': getToken() || '',
		'Content-Type': 'application/json;charset=UTF-8',
		...params.header
	};


	return new Promise((resolve, reject) => {
		// 显示加载提示
		uni.showLoading({
			title: '加载中...'
		});

		uni.request({
			url: base_url + url,
			method: method,
			header: header,
			data: data,
			timeout: timeout,
			success(response) {
				const res = response;
				// 根据返回的状态码做出对应的操作
				// console.log()
				if (res.data.code === 200) {
					resolve(res.data);
				} else {
					uni.clearStorageSync();
					switch (res.data.code) {
						case 401:
							uni.showModal({
								title: "提示",
								content: "请登录",
								showCancel: false,
								success() {
									setTimeout(() => {
										uni.redirectTo({
											url: "/pages/login/login",
										});
									}, 1000);
								},
							});
							break;
						case 404:
							uni.showToast({
								title: '请求地址不存在...',
								duration: 2000,
							});
							break;
						default:
							uni.showToast({
								title: '请重试...',
								duration: 2000,
							});
							break;
					}
				}
			},
			fail(err) {
				console.log(err);
				if (err.errMsg.indexOf('request:fail') !== -1) {
					uni.showToast({
						title: '网络异常',
						icon: "error",
						duration: 2000,
					});
				} else {
					uni.showToast({
						title: '未知异常',
						duration: 2000,
					});
				}
				reject(err);
			},
			complete() {
				// 不管成功还是失败都会执行
				uni.hideLoading();
				uni.hideToast();
			}
		});
	}).catch(() => {});
};

封装请求:

//api/api.js
import {
	request
} from "@/utils/request.js"
const baseUrl = "/wallpaper"

export function apiGetBanner(query) {
	return request({
		url: baseUrl + '/banner/list',
		method: 'get',
		params: query
	})
}

使用:

	import {
		apiGetBanner,
	} from "@/api/apis.js"

	const getBanner = async () => {
		let res = await apiGetBanner();
		bannerList.value = res.rows;
		console.log(res);
	}

条件编译

  • 通过特殊注释,以 #ifdef#ifndef%PLATFORM% 开头,以 #endif 结尾。%PLATFORM% 常用取值:MP(大部分小程序),WEB(网页),APP
  • 多平台编译:#ifdef H5 || MP-WEIXIN 表示在 H5 端 或 微信小程序端 代码。
  • 条件编译支持: 支持 .vue, .ts, .js, .scss, .css, pages.json 等文件。

<script setup lang="ts">
  // 微信平台特有API,需要条件编译
  // #ifdef MP-WEIXIN
  wx.login()
  wx.requestPayment()
  // #endif
</script>

<template>
  <!-- 微信开发能力按钮,需要条件编译 -->
  <!-- #ifdef MP-WEIXIN -->
  <button open-type="openSetting">授权管理</button>
  <button open-type="feedback">问题反馈</button>
  <button open-type="contact">联系我们</button>
  <!-- #endif -->
</template>

  <style>
  /* 如果出现样式兼容,也可添加条件编译 */
  page {
  /* #ifdef H5 */
  background-color: pink;
  /* #endif */
  }
</style>

更多查看官方文档

插件/依赖安装

官方插件



DCloud 插件市场

进入官方插件市场,搜索需要引入的插件(包括官方组件库uni-ui)

例如:
 



点击链接,跳转到uni-forms 表单 - DCloud 插件市场
点击下载并导入
 



重新运行项目即可
 

命令行

使用npm安装即可

组件库

uni-ui

引入 uni-ui 组件库:

pnpm i @dcloudio/uni-ui

配置自动导入组件:

// pages.json
{
  // 组件自动导入
  "easycom": {
    "autoscan": true,
    "custom": {
      // uni-ui 规则如下配置  
      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" 
    }
  },
  "pages": [
    // …省略
  ]
}

安装类型声明文件

pnpm i -D @uni-helper/uni-ui-types

在tsconfig.json中配置:

// 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"]
  }
}

uView-Plus

uni-ui是官方提供的组件库,而uView-Plus是uniapp的第三方组件库

官方组件库提供的组件有限,且大部分没有示例

官方文档

pnpm add uview-plus
pnpm add dayjs
pnpm add clipboard

因为uview-plus依赖SCSS,所以必须要安装此插件,否则无法正常运行。

在项目src目录中的main.js中,引入并使用uview-plus的JS库

// main.js
import uviewPlus from 'uview-plus'
import App from "./App.vue";
import { createSSRApp } from "vue";
import pinia from './stores'

export function createApp() {
  const app = createSSRApp(App);
  app.use(pinia)
  app.use(uviewPlus)
  return {
    app,
  };
}

在项目根目录的uni.scss中,引入uview-plus的全局SCSS主题文件

/* uni.scss */
@import 'uview-plus/theme.scss';

App.vue首行的位置引入uview-plus基础样式,注意给style标签加入lang="scss"属性

// App.vue
<style lang="scss">
	/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
	@import "uview-plus/index.scss";
</style>

在项目src目录的pages.json中配置easycom组件模式

// pages.json
{
	"easycom": {
		// 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
		"custom": {
			"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
			"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
	    "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
		}
	},
	
	// 此为本身已有的内容
	"pages": [
		// ......
	]
}

在types文件中新建uview.d.ts文件写入下方声明代码:

declare module "uview-plus"

使用

<u-button text="提交"></u-button>
或
<up-button text="提交"></up-button>

避免与uni-ui冲突等问题参考文档

element plus

实际上,如果你使用了命令行开发,你甚至可以使用element plus
 

首先,安装依赖:

npm install element-plus --save

安装自动导入插件

npm install -D unplugin-vue-components unplugin-auto-import

配置自动导入(vite.config.js):

import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    // 开发阶段启用源码映射:https://uniapp.dcloud.net.cn/tutorial/migration-to-vue3.html#需主动开启-sourcemap
    sourcemap: process.env.NODE_ENV === 'development',
  },
  plugins: [
    uni(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    })
  ],
})

现在uniapp项目可以使用element plus了:

效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值