uniapp 入门
阅读原文时间:2023年07月08日阅读:14

uniapp官网

uni-app 是一个使用 Vue.js (opens new window)开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。

新建uni-app

运行uni-app

uniapp 初始化相关配置

一个uni-app工程,默认包含如下目录及文件:

┌─uniCloud              云空间目录,阿里云为uniCloud-aliyun,腾讯云为uniCloud-tcb(详见uniCloud)
│─components            符合vue组件规范的uni-app组件目录
│  └─comp-a.vue         可复用的a组件
├─hybrid                App端存放本地html文件的目录,详见
├─platforms             存放各平台专用页面的目录,详见
├─pages                 业务页面文件存放的目录
│  ├─index
│  │  └─index.vue       index页面
│  └─list
│     └─list.vue        list页面
├─static                存放应用引用的本地静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此
├─uni_modules           存放[uni_module](/uni_modules)规范的插件。
├─wxcomponents          存放小程序组件的目录,详见
├─main.js               Vue初始化入口文件
├─App.vue               应用配置,用来配置App全局样式以及监听 应用生命周期
├─manifest.json         配置应用名称、appid、logo、版本等打包信息,详见
├─pages.json            配置页面路由、导航条、选项卡等页面类信息,详见
└─uni.scss              这里是uni-app内置的常用样式变量
  • 编译到任意平台时,static 目录下的文件均会被完整打包进去,且不会编译。非 static 目录下的文件(vue、js、css 等)只有被引用到才会被打包编译进去。
  • static 目录下的 js 文件不会被编译,如果里面有 es6 的代码,不经过转换直接运行,在手机设备上会报错。
  • css、less/scss 等资源不要放在 static 目录下,建议这些公用的资源放在自建的 common 目录下。
  • HbuilderX 1.9.0+ 支持在根目录创建 ext.json、sitemap.json 等小程序需要的文件。

manifest.json 应用配置

是应用的配置文件,用于指定应用的名称、图标、权限等。也可以在这里为Vue,为H5设置跨域拦截处理器

vue.config.js 编译配置地址

vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。你也可以使用 package.json 中的 vue 字段,但是注意这种写法需要你严格遵照 JSON 的格式来写。

这个文件应该导出一个包含了选项的对象:

// vue.config.js

/**
 * @type {import('@vue/cli-service').ProjectOptions}
 */
module.exports = {
  // 选项...
}

或者,你也可以使用 @vue/cli-service 提供的 defineConfig 帮手函数,以获得更好的类型提示:

// vue.config.js
const { defineConfig } = require('@vue/cli-service')

module.exports = defineConfig({
  // 选项
})

package.json 全局配置

用来对uni-app进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar等。它类似微信小程序中app.json的页面管理部分

{
    /**
     * package.json其它原有配置
     * 拷贝代码后请去掉注释!
     */
    "uni-app": {// 扩展配置
        "scripts": {
            "custom-platform": { //自定义编译平台配置,可通过cli方式调用
                "title":"自定义扩展名称", // 在HBuilderX中会显示在 运行/发行 菜单中
                "browser":"",  //运行到的目标浏览器,仅当UNI_PLATFORM为h5时有效
                "env": {//环境变量
                    "UNI_PLATFORM": "",  //基准平台
                    "MY_TEST": "", // ... 其他自定义环境变量
                 },
                "define": { //自定义条件编译
                    "CUSTOM-CONST": true //自定义条件编译常量,建议为大写
                }
            }
        }
    }
}

App.vue

是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面入口文件。但App.vue本身不是页面,这里不能编写视图元素。

这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData

应用生命周期仅可在App.vue中监听,在页面监听无效

uni-app 支持如下应用生命周期函数:

函数名

说明

onLaunch

当uni-app 初始化完成时触发(全局只触发一次)

onShow

当 uni-app 启动,或从后台进入前台显示

onHide

当 uni-app 从前台进入后台

onError

当 uni-app 报错时触发

onUniNViewMessage

对 nvue 页面发送的数据进行监听,可参考 nvue 向 vue 通讯(opens new window)

onUnhandledRejection

对未处理的 Promise 拒绝事件监听函数(2.8.1+)

onPageNotFound

页面不存在监听函数

onThemeChange

监听系统主题变化

<script>
    // 只能在App.vue里监听应用的生命周期
    export default {
        onLaunch: function() {
            console.log('App Launch')
        },
        onShow: function() {
            console.log('App Show')
        },
        onHide: function() {
            console.log('App Hide')
        },
        onPageNotFound() {
            uni.navigateTo({
                url:'/pages/404/404'
            })
        }
    }
</script>

uni.scss 官方地址

文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss文件里预置了一批scss变量预置。

main.js 入口文件官方地址

main.js是 uni-app 的入口文件,主要作用是初始化vue实例、定义全局组件、使用需要的插件如 vuex。

***************************vue2
import Vue from 'vue'
import App from './App'
import pageHead from './components/page-head.vue' //全局引用 page-head 组件

Vue.config.productionTip = false
Vue.component('page-head', pageHead) //全局注册 page-head 组件,每个页面将可以直接使用该组件
App.mpType = 'app'

const app = new Vue({
...App
})
app.$mount() //挂载 Vue 实例

**************************vue3
import App from './App'
import { createSSRApp } from 'vue'
export function createApp() {
    const app = createSSRApp(App)
    return {
        app
    }
}

uniapp 开发规范及资源路径

为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:

  • 页面文件遵循 Vue 单文件组件 (SFC) 规范

  • 组件标签靠近小程序规范,详见uni-app 组件规范

  • 接口能力(JS API)靠近微信小程序规范,但需将前缀 wx 替换为 uni,详见uni-app接口规范

  • 数据绑定及事件处理同 Vue.js 规范,同时补充了App及页面的生命周期

  • 为兼容多端运行,建议使用flex布局进行开发

  • 在 uni-app 项目中,页面引用组件和组件引用组件的方式都是一样的(可以理解为:页面是一种特殊的组件),均支持通过 easycom 方式直接引用。

easycom 规范详细介绍,参考:easycom

  • js 文件引入

js文件或script标签内(包括 renderjs 等)引入js文件时,可以使用相对路径和绝对路径,形式如下

// 绝对路径,@指向项目根目录,在cli项目中@指向src目录
import add from '@/common/add.js';
// 相对路径
import add from '../../common/add.js';
// Tips
// js 文件不支持使用/开头的方式引入
  • NPM支持

uni-app支持使用npm安装第三方包。

  • css 文件引入

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。

<style>
    @import "../../common/uni.css";

    .uni-card {
        box-shadow: none;
    }
</style>
  • 模板内引入静态资源

template内引入静态资源,如image、video等标签的src属性时,可以使用相对路径或者绝对路径,形式如下

<!-- 绝对路径,/static指根目录下的static目录,在cli项目中/static指src目录下的static目录 -->
<image class="logo" src="/static/logo.png"></image>
<image class="logo" src="@/static/logo.png"></image>
<!-- 相对路径 -->
<image class="logo" src="../../static/logo.png"></image>

Tips:

  • @开头的绝对路径以及相对路径会经过 base64 转换规则校验
  • 引入的静态资源在非 h5 平台,均不转为 base64。
  • H5 平台,小于 4kb 的资源会被转换成 base64,其余不转。
  • 自HBuilderX 2.6.6起template内支持@开头路径引入静态资源,旧版本不支持此方式
  • App 平台自HBuilderX 2.6.9起template节点中引用静态资源文件时(如:图片),调整查找策略为【基于当前文件的路径搜索】,与其他平台保持一致
  • 支付宝小程序组件内 image 标签不可使用相对路径

uniapp 生命周期

uni-app 支持如下页面生命周期函数:

函数名

说明

平台差异说明

最低版本

onInit

监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object(用于页面传参),触发时机早于 onLoad

百度小程序

3.1.0+

onLoad

监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例

onShow

监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面

onReady

监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发

onHide

监听页面隐藏

onUnload

监听页面卸载

onResize

监听窗口尺寸变化

App、微信小程序、快手小程序

onPullDownRefresh

监听用户下拉动作,一般用于下拉刷新,参考示例

onReachBottom

页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项

onTabItemTap

点击 tab 时触发,参数为Object,具体见下方注意事项

微信小程序、QQ小程序、支付宝小程序、百度小程序、H5、App、快手小程序、京东小程序

onShareAppMessage

用户点击右上角分享

微信小程序、QQ小程序、支付宝小程序、字节小程序、飞书小程序、快手小程序、京东小程序

onPageScroll

监听页面滚动,参数为Object

nvue暂不支持

onNavigationBarButtonTap

监听原生标题栏按钮点击事件,参数为Object

App、H5

onBackPress

监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack ;详细说明及使用:onBackPress 详解 (opens new window)。支付宝小程序只有真机能触发,只能监听非navigateBack引起的返回,不可阻止默认行为。

app、H5、支付宝小程序

onNavigationBarSearchInputChanged

监听原生标题栏搜索输入框输入内容变化事件

App、H5

1.6.0

onNavigationBarSearchInputConfirmed

监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发。

App、H5

1.6.0

onNavigationBarSearchInputClicked

监听原生标题栏搜索输入框点击事件(pages.json 中的 searchInput 配置 disabled 为 true 时才会触发)

App、H5

1.6.0

onShareTimeline

监听用户点击右上角转发到朋友圈

微信小程序

2.8.1+

onAddToFavorites

监听用户点击右上角收藏

微信小程序

2.8.1+

uni-app 组件支持的生命周期,与vue标准组件的生命周期相同。这里没有页面级的onLoad等生命周期:

// APP.vue 中 添加页面找不到
onPageNotFound() {
            uni.navigateTo({
                url:'/pages/404/404'
            })
        }
// 404 页面中
onLoad() {
let timer = setTimeout(()=>{
    clearTimeout(timer);
    uni.navigateTo({
         url:'/pages/index/index'
          })
    },2000);
}

通过HBuilderX开发 uni-app 项目时,在 uni-app 项目上右键“新建页面”,HBuilderX会自动在pages.json中完成页面注册,开发更方便。

同时,HBuilderX 还内置了常用的页面模板(如图文列表、商品列表等),选择这些模板,可以大幅提升你的开发效率。

uniapp 路由配置及页面跳转

uni-app页面路由为框架统一管理,开发者需要在pages.json里配置每个路由页面的路径及页面样式。类似小程序在 app.json 中配置页面路由一样。所以 uni-app 的路由用法与 Vue Router 不同,如仍希望采用 Vue Router 方式管理路由,可在插件市场搜索 Vue-Router

配置项列表

属性

类型

必填

描述

平台兼容

globalStyle

Object

设置默认页面的窗口表现

pages

Object Array

设置页面路径及窗口表现

easycom

Object

组件自动引入规则

2.5.5+

tabBar

Object

设置底部 tab 的表现

condition

Object

启动模式配置

subPackages

Object Array

分包加载配置

preloadRule

Object

分包预下载规则

微信小程序

workers(opens new window)

String

Worker 代码放置的目录

微信小程序

leftWindow

Object

大屏左侧窗口

H5

topWindow

Object

大屏顶部窗口

H5

rightWindow

Object

大屏右侧窗口

H5

///包含了所有配置选项的 pages.json :
{
    "pages": [{
        "path": "pages/component/index",
        "style": {
            "navigationBarTitleText": "组件"
        }
    }, {
        "path": "pages/API/index",
        "style": {
            "navigationBarTitleText": "接口"
        }
    }, {
        "path": "pages/component/view/index",
        "style": {
            "navigationBarTitleText": "view"
        }
    }],
    "condition": { //模式配置,仅开发期间生效
        "current": 0, //当前激活的模式(list 的索引项)
        "list": [{
            "name": "test", //模式名称
            "path": "pages/component/view/index" //启动页面,必选
        }]
    },
    "globalStyle": {
        "navigationBarTextStyle": "black",
        "navigationBarTitleText": "演示",
        "navigationBarBackgroundColor": "#F8F8F8",
        "backgroundColor": "#F8F8F8",
        "usingComponents":{
            "collapse-tree-item":"/components/collapse-tree-item"
        },
        "renderingMode": "seperated", // 仅微信小程序,webrtc 无法正常时尝试强制关闭同层渲染
        "pageOrientation": "portrait", //横屏配置,全局屏幕旋转设置(仅 APP/微信/QQ小程序),支持 auto / portrait / landscape
        "rpxCalcMaxDeviceWidth": 960,
        "rpxCalcBaseDeviceWidth": 375,
        "rpxCalcIncludeWidth": 750
    },
    "tabBar": {
        "color": "#7A7E83",
        "selectedColor": "#3cc51f",
        "borderStyle": "black",
        "backgroundColor": "#ffffff",
        "height": "50px",
        "fontSize": "10px",
        "iconWidth": "24px",
        "spacing": "3px",
    "iconfontSrc":"static/iconfont.ttf", // app tabbar 字体.ttf文件路径 app 3.4.4+
        "list": [{
            "pagePath": "pages/component/index",
            "iconPath": "static/image/icon_component.png",
            "selectedIconPath": "static/image/icon_component_HL.png",
            "text": "组件",
      "iconfont": { // 优先级高于 iconPath,该属性依赖 tabbar 根节点的 iconfontSrc
        "text": "\ue102",
        "selectedText": "\ue103",
        "fontSize": "17px",
        "color": "#000000",
        "selectedColor": "#0000ff"
      }
        }, {
            "pagePath": "pages/API/index",
            "iconPath": "static/image/icon_API.png",
            "selectedIconPath": "static/image/icon_API_HL.png",
            "text": "接口"
        }],
        "midButton": {
            "width": "80px",
            "height": "50px",
            "text": "文字",
            "iconPath": "static/image/midButton_iconPath.png",
            "iconWidth": "24px",
            "backgroundImage": "static/image/midButton_backgroundImage.png"
        }
    },
  "easycom": {
    "autoscan": true, //是否自动扫描组件
    "custom": {//自定义扫描规则
      "^uni-(.*)": "@/components/uni-$1.vue"
    }
  },
  "topWindow": {
    "path": "responsive/top-window.vue",
    "style": {
      "height": "44px"
    }
  },
  "leftWindow": {
    "path": "responsive/left-window.vue",
    "style": {
      "width": "300px"
    }
  },
  "rightWindow": {
    "path": "responsive/right-window.vue",
    "style": {
      "width": "300px"
    },
    "matchMedia": {
      "minWidth": 768
    }
  }
}

uni-app 有两种页面路由跳转方式:使用navigator组件跳转、调用API跳转

页面栈

框架以栈的形式管理当前所有页面, 当发生路由切换的时候,页面栈的表现如下:

路由方式

页面栈表现

触发时机

初始化

新页面入栈

uni-app 打开的第一个页面

打开新页面

新页面入栈

调用 API uni.navigateTo 、使用组件

页面重定向

当前页面出栈,新页面入栈

调用 API uni.redirectTo 、使用组件

页面返回

页面不断出栈,直到目标返回页

调用 API uni.navigateBack 、使用组件 、用户按左上角返回按钮、安卓用户点击物理back按键

Tab 切换

页面全部出栈,只留下新的 Tab 页面

调用 API uni.switchTab 、使用组件 、用户切换 Tab

重加载

页面全部出栈,只留下新的页面

调用 API uni.reLaunch 、使用组件

getCurrentPages()

getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。

注意: getCurrentPages()仅用于展示页面栈的情况,请勿修改页面栈,以免造成页面状态错误。

Tips:

  • navigateTo, redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 不能在 App.vue 里面进行页面跳转。

subPackages

分包加载配置,此配置为小程序的分包加载机制。

因小程序有体积和资源加载限制,各家小程序平台提供了分包方式,优化小程序的下载和启动速度。

所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据pages.json的配置进行划分。

在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,会把对应分包自动下载下来,下载完成后再进行展示。此时终端界面会有等待提示。

App默认为整包。从uni-app 2.7.12+ 开始,也兼容了小程序的分包配置。其目的不用于下载提速,而用于首页是vue时的启动提速。App下开启分包,除在pages.json中配置分包规则外,还需要在manifest中设置在app端开启分包设置,详见:https://uniapp.dcloud.io/collocation/manifest?id=app-vue-optimization

subPackages 节点接收一个数组,数组每一项都是应用的子包,其属性值如下:

属性

类型

是否必填

描述

root

String

子包的根目录

pages

Array

子包由哪些页面组成,参数同 pages

{
    "pages": [{
        "path": "pages/index/index",
        "style": { ...}
    }, {
        "path": "pages/login/login",
        "style": { ...}
    }],
    "subPackages": [{
        "root": "pagesA",
        "pages": [{
            "path": "list/list",
            "style": { ...}
        }]
    }, {
        "root": "pagesB",
        "pages": [{
            "path": "detail/detail",
            "style": { ...}
        }]
    }],
    "preloadRule": {
        "pagesA/list/list": {
            "network": "all",
            "packages": ["__APP__"]
        },
        "pagesB/detail/detail": {
            "network": "all",
            "packages": ["pagesA"]
        }
    }
}

组件(官方文档

  • 组件是视图层的基本组成单元。

  • 组件是一个单独且可复用的功能模块的封装。

  • 每个组件,包括如下几个部分:以组件名称为标记的开始标签和结束标签、组件内容、组件属性、组件属性值。

  • 组件名称由尖括号包裹,称为标签,它有开始标签和结束标签。结束标签的<后面用/来表示结束。结束标签也称为闭合标签。如下面示例的是开始标签,是结束标签。

  • 在开始标签和结束标签之间,称为组件内容。如下面示例的content

  • 开始标签上可以写属性,属性可以有多个,多个属性之间用空格分割。如下面示例的property1和property2。注意闭合标签上不能写属性。

  • 每个属性通过=赋值。如下面的示例中,属性property1的值被设为字符串value。

注意:所有组件与属性名都是小写,单词之间以连字符-连接。

<template>
    <view>
        <button size="mini">按钮</button>
    </view>
</template>