uniapp基础笔记

与html区别

uni-app简单来说是 vue的语法 + 小程序的api。

文件结构

html

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script type="text/javascript">
			
		</script>
		<style type="text/css">
			
		</style>
	</head>
	<body>
		
	</body>
</html>

uniapp

vue 复制代码
<template>
	<view>
	注意必须有一个view,且只能有一个根view。所有内容写在这个view下面。
	</view>
</template>

<script>
	export default {
		
	}
</script>

<style>

</style>

文件引入

html

以前通过script src、link href引入外部的js和css;

html 复制代码
<script src="js/jquery-1.10.2.js" type="text/javascript"></script>
<link href="css/bootstrap.css" rel="stylesheet" type="text/css"/>

js要require进来,变成了对象。

js 复制代码
<script>
var util = require('../../../common/util.js');  //require这个js模块
var formatedPlayTime = util.formatTime(playTime); //调用js模块的方法
</script>

CSS

CSS 复制代码
<style>
	@import "./common/uni.css";
	
	.uni-hello-text{
		color:#7A7E83;
	}
</style>

全局样式,在根目录下的app.vue里写入,每个页面都会加载app.vue里的样式。

单组件引入
vue 复制代码
<template>
	<view>
		<uni-badge text="abc" :inverted="true"></uni-badge><!--3.使用组件-->
	</view>
</template>
<script>
	import uniBadge from "../../../components/uni-badge.vue";//1.导入组件(这步属于传统vue规范,但在uni-app的easycom下可以省略这步)
	export default {
		data() {
			return {
				
			}
		},
		components: {
			uniBadge //2.注册组件(这步属于传统vue规范,但在uni-app的easycom下可以省略这步)
		}
	}
</script>
js文件引入

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

js 复制代码
// 绝对路径,@指向项目根目录,在cli项目中@指向src目录
import add from '@/common/add.js';
// 相对路径
import add from '../../common/add.js';

注意

  • js 文件不支持使用/开头的方式引入
css文件引入

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

示例代码:

html 复制代码
<style>
    @import "../../common/uni.css";

    .uni-card {
        box-shadow: none;
    }
</style>
静态资源

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

html 复制代码
<!-- 绝对路径,/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>

根目录下的 static 为静态资源文件夹(目前暂不支持修改),资源存放此处后,可在任意文件直接使用相对或者绝对路径引用,具体参考上述模板 css/js/uts 中引入静态资源的说明。

而非 static 目录的静态资源,不支持直接引用,需要在 js/uts 中使用 import 来引入,确保路径正确。

标签变化

uni-app参考小程序规范,提供了一批内置组件。

下为html标签和uni-app内置组件的映射表:

除了改动外,新增了一批手机端常用的新组件

除了内置组件,还有很多开源的扩展组件,把常用操作都进行封装,DCloud建立了插件市场收录这些扩展组件,详见插件市场

js的变化

  • 运行环境从浏览器变成v8引擎

js是ECMAScript组织管理的,浏览器中的js是w3c组织基于js规范补充了window、document、navigator、location等专用对象。这些对象只有在浏览器中才有,app和小程序都不支持。

在uni-app的各个端中,除了h5端,其他端的js都运行在一个独立的v8引擎下,不是在浏览器中,所以浏览器的对象无法使用。

这意味着依赖document的很多HTML的库,比如jquery无法使用。

当然app和小程序支持web-view组件,里面可以加载标准HTML,这种页面仍然支持浏览器专用对象window、document、navigator、location。

  • 以前的dom操作,改成vue的MVVM模式

现在前端趋势是去dom化,改用mvvm模式,更简洁的写法,大幅减少代码行数,同时差量渲染性能更好。

uni-app使用vue的数据绑定方式解决js和dom界面交互的问题。

参考vue`

vue 复制代码
<template>
	<view>
		<text>{{textvalue}}</text><!-- 这里演示了组件值的绑定 -->
		<button :type="buttontype" @click="changetextvalue()">修改为789</button><!-- 这里演示了属性和事件的绑定 -->
	</view>
</template>

<script>
	export default {
		data() {
			return {
				textvalue:"123",
				buttontype:"primary"
			};
		},
		onLoad() {
			this.textvalue="456"//这里修改textvalue的值,其实123都来不及显示就变成了456
		},
		methods: {
			changetextvalue() {
				this.textvalue="789"//这里修改textvalue的值,页面自动刷新为789
			}
		}
	}
</script>

代码中的 export default {} 里的 data(): {return { }}。 在vue的设计中,这里存放着页面中需要绑定的数据,写在data里,才能被界面正确的绑定和渲染。 注意:uni-app的vue页面是vue的单文件组件规范,按照vue的定义只接受 function,必须用 return 包起来。

数据绑定与小程序区别

如果你学过小程序的数据绑定,但不了解vue,要注意:

  • 小程序的数据绑定参考了vue,但自己修改了一些。在uni-app中只支持标准的vue,不支持小程序的数据绑定语法

  • 小程序里的setData在uni-app里并不存在,因为vue是自动双向数据绑定的。直接通过赋值方式修改数据,如果数据绑定到界面上,界面会自动更新渲染

  • js api的变化

因为uni-app的api是参考小程序的,所以和浏览器的js api有很多不同,如

  1. alert,confirm 改成 uni.showmodel
  2. ajax 改成 uni.request
  3. cookie、session 没有了,local.storage 改成 uni.storage

uni-app的js api还有很多,但基本就是小程序的api,把wx.xxx改为uni.xxx即可。详见

uni-app在不同的端,支持条件编译,无限制的使用各端独有的api,详见条件编译

CSS的变化

标准的css基本都是支持的。

选择器有2个变化:*选择器不支持;元素选择器里没有body,改为了page。微信小程序即是如此。

css 复制代码
page{
	
}

单位方面,px无法动态适应不同宽度的屏幕,rem无法用于nvue/weex。如果想使用根据屏幕宽度自适应的单位,推荐使用rpx,全端支持。 尺寸单位文档

uni-app推荐使用flex布局,这个布局思路和传统流式布局有点区别。但flex的特色在于,不管是什么技术都支持这种排版,web、小程序/快应用、weex/rn、原生的iOS、Android开发,全都支持flex。它是通吃所有端的新一代布局方案。相关教程请自行百度学习。

uni-app的vue文件里支持所有web排版方式,不管是流式还是flex。但nvue里,只支持flex,因为它在app端是使用原生排版引擎渲染的。

注意css里背景图和字体文件,尽量不要大于40k,因为会影响性能。在小程序端,如果要大于40k,需放到服务器侧远程引用或base64后引入,不能放到本地作为独立文件引用。

工程结构

每个可显示的页面,都必须在 pages.json 中注册。

原来工程的首页一般是index.html或default.html,是在web server里配的。而uni-app的首页,是在pages.json里配的,page节点下第一个页面就是首页。一般在/pages/xx的目录下。

app和小程序中,为了提升体验,页面提供了原生的导航栏和底部tabbar,注意这些配置是在pages.json中做,而不是在vue页面里创建,但点击事件的监听在显示的vue页面中做。

APP渲染方式区别

  • webview渲染方式,架构和微信小程序一样。微信小程序的Hybrid应用框架是业内体验上的标杆,实践证明这种体验足以承载一线互联网开发商获得上亿用户。uni-app的App端体验同微信小程序,超过其他平台的小程序,超过一般的hybrid框架。
  • 原生渲染方式,是DCloud改造了weex引擎,在原生渲染引擎上实现了uni-app的组件和API。达到更优秀的用户体验。

uniapp写微信小程序好处

  1. 使用vue语法开发,不用学小程序语法
  2. uni-app支持双向数据绑定、vuex状态管理,比小程序原生开发方便的多

工程目录

static

图片等文件,此目录下所有文件被编译

common

公用的css less scss等,按引入编译

页面

后缀名是.vue文件或.nvue文件

.vue文件会使用webview进行渲染,.nvue会使用原生进行渲染

新建

uni-app中的页面,默认保存在工程根目录下的pages目录下。

每次新建页面,均需在pages.json中配置pages列表;未在pages.json -> pages 中注册的页面,uni-app会在编译阶段进行忽略。pages.json的完整配置参考:页面配置

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

页面组成

uni-app 页面基于 vue 规范。一个页面内,有3个根节点标签:

  • 模板组件区 <template>
  • 脚本区 <script>
  • 样式区 <style>
template模板
  1. html中 scriptstyle 是 html 的二级节点。但在 vue 文件中,templatescriptstyle 这3个是平级关系。
  2. html 中写的是 web 标签,但 vue 的 template 中写的全都是 vue 组件,每个组件支持属性、事件、 vue 指令,还可以绑定 vue 的 data 数据。
script 脚本区

cript中编写脚本,可以通过lang属性指定脚本语言。

  • 在vue和nvue中,默认是js,可以指定ts。
  • 在uvue中,仅支持uts,不管script的lang属性写成什么,都按uts编译。
export default` 外的代码

写在 export default {} 外面的代码,一般有几种情况:

  1. 引入第三方 js/ts 模块
  2. 引入非 easycom 的组件(一般组件推荐使用easycom,无需导入注册)
  3. 在 ts/uts 中,对 data 进行类型定义
  4. 定义作用域更大的变量

开发者应谨慎编写 export default {} 外面的代码,这里的代码有2个注意事项:

  1. 影响应用性能。这部分代码在应用启动时执行,而不是页面加载。如果这里的代码写的太复杂,会影响应用启动速度,占用更多内存。
  2. 不跟随组件、页面关闭而回收。在外层的静态变量不会跟随页面关闭而回收。如果必要你需要手动处理。比如 beforeDestroydestroyed 生命周期进行处理。
export default 里的代码

export default {} 里的内容,是页面的主要逻辑代码。包括几部分:

  1. data:template模板中需要使用的数据。具体 另见
  2. 页面生命周期:如页面加载、隐藏、关闭,具体 见下
  3. methods方法,如按钮点击、屏幕滚动

如下页面代码的逻辑是:

  1. 在data中定义了title,初始值是"点我"
  2. 在页面中放置了一个button组件,按钮文字区使用{``{}}模板写法,里面写title,把data里的title绑定到按钮的文字区,即按钮的初始文字是"点我"
  3. 按钮的点击事件@click,指向了methods里的一个方法buttonClick,点击按钮即触发这个方法的执行
  4. buttonClick方法里通过this.title的方式,访问data数据,并重新赋值为"被点了"。由于vue中data和界面是双向绑定,修改data中的title后,因为按钮文字绑定了title,会自动更新按钮的文字。
style样式区

style的写法与web的css基本相同。

如果页面是nvue或uvue,使用原生渲染而不是webview渲染,那么它们支持的css是有限的。

页面生命周期

onLoad比较适合的操作是:接受上页的参数,联网取数据,更新data。

onReady后,页面元素就可以自由操作了,比如ref获取节点。同时首批界面也渲染了。

页面通信

uni.$emit(eventName,OBJECT)

uni.$on(eventName,callback)

uni.$once(eventName,callback)

uni.$off([eventName, callback])

  • 如果没有提供参数,则移除所有的事件监听器;
  • 如果只提供了事件,则移除该事件所有的监听器;
  • 如果同时提供了事件与回调,则只移除这个回调的监听器;
  • 提供的回调必须跟$on的回调为同一个才能移除这个回调的监听器;
  • uni. e m i t 、 u n i . emit、 uni. emit、uni.on 、 uni. o n c e 、 u n i . once 、uni. once、uni.off 触发的事件都是 App 全局级别的,跨任意组件,页面,nvue,vue 等
  • 使用时,注意及时销毁事件监听,比如,页面 onLoad 里边 uni. o n 注册监听, o n U n l o a d 里边 u n i . on 注册监听,onUnload 里边 uni. on注册监听,onUnload里边uni.off 移除,或者一次性的事件,直接使用 uni.$once 监听"

路由

uni-app页面路由为框架统一管理,开发者需要在pages.json里配置每个路由页面的路径及页面样式。

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

页面返回时会自动关闭 loading 及 toast, modal 及 actionSheet 不会自动关闭。

页面关闭时,只是销毁了页面实例,未完成的网络请求、计时器等副作用需开发者自行处理。

npm支持

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

初始化npm工程

若项目之前未使用npm管理依赖(项目根目录下无package.json文件),先在项目根目录执行命令初始化npm工程:

shell 复制代码
npm init -y

复制代码

cli项目默认已经有package.json了。HBuilderX创建的项目默认没有,需要通过初始化命令来创建。

安装依赖

在项目根目录执行命令安装npm包:

shell 复制代码
npm install packageName --save

复制代码

使用

安装完即可使用npm包,js中引入npm包:

js 复制代码
import package from 'packageName'
const package = require('packageName')

复制代码

注意

  • 为多端兼容考虑,建议优先从 uni-app插件市场 获取插件。直接从 npm 下载库很容易只兼容H5端。
  • 非 H5 端不支持使用含有 dom、window 等操作的 vue 组件和 js 模块,安装的模块及其依赖的模块使用的 API 必须是 uni-app 已有的 API(兼容小程序 API),比如:支持高德地图微信小程序 SDK。类似jQuery 等库只能用于H5端。
  • node_modules 目录必须在项目根目录下。不管是cli项目还是HBuilderX创建的项目。
  • 关于ui库的获取,详见多端UI库

rpx

rpx 详细说明:

设计师在提供设计图时,一般只提供一个分辨率的图。

严格按设计图标注的 px 做开发,在不同宽度的手机上界面很容易变形。

而且主要是宽度变形。高度一般因为有滚动条,不容易出问题。由此,引发了较强的动态宽度单位需求。

微信小程序设计了 rpx 解决这个问题。uni-app 在 App 端、H5 端都支持了 rpx,并且可以配置不同屏幕宽度的计算方式,具体参考:rpx 计算配置

rpx 是相对于基准宽度的单位,可以根据屏幕宽度进行自适应。uni-app 规定屏幕基准宽度 750rpx。

开发者可以通过设计稿基准宽度计算页面元素 rpx 值,设计稿 1px 与框架样式 1rpx 转换公式如下:

设计稿 1px / 设计稿基准宽度 = 框架样式 1rpx / 750rpx

换言之,页面元素宽度在 uni-app 中的宽度计算公式:

750 * 元素在设计稿中的宽度 / 设计稿基准宽度
  • 注意 rpx 是和宽度相关的单位,屏幕越宽,该值实际像素越大。如不想根据屏幕宽度缩放,则应该使用 px 单位。
  • 如果开发者在字体或高度中也使用了 rpx ,那么需注意这样的写法意味着随着屏幕变宽,字体会变大、高度会变大。如果你需要固定高度,则应该使用 px 。
  • rpx 不支持动态横竖屏切换计算,使用 rpx 建议锁定屏幕方向
  • 设计师可以用 iPhone6 作为视觉稿的标准。
  • 如果设计稿不是 750px,HBuilderX 提供了自动换算的工具,详见:HBuilderX中自动转换px为upx
  • App 端,在 pages.json 里的 titleNView 或页面里写的 plus api 中涉及的单位,只支持 px,不支持 rpx。

内联样式

框架组件上支持使用 style、class 属性来控制组件的样式。

  • style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
html 复制代码
<view :style="{color:color}" />
  • class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。
html 复制代码
<view class="normal_view" />

选择器

目前支持的选择器有:

选择器 样例 样例描述
.class .intro 选择所有拥有 class="intro" 的组件
#id #firstname 选择拥有 id="firstname" 的组件
element view 选择所有 view 组件
element, element view, checkbox 选择所有文档的 view 组件和所有的 checkbox 组件
::after view::after 在 view 组件后边插入内容,仅 vue 页面生效
::before view::before 在 view 组件前边插入内容,仅 vue 页面生效

注意:

  • uni-app 中不能使用 * 选择器。

  • 微信小程序自定义组件中仅支持 class 选择器

  • page 相当于 body 节点,例如:

    css 复制代码
    <!-- 设置页面背景颜色,使用 scoped 会导致失效 -- >
    page {
      background-color: #ccc;
    }

    复制代码

  • web端可以使用htmlbody:root等选择器。由于页面的css样式隔离,且html节点并未添加data-xxx属性,html:root写在页面style内无效,只能写在App.vue内

全局样式与局部样式

定义在 App.vue 中的样式为全局样式,作用于每一个页面。在 pages 目录下 的 vue 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 App.vue 中相同的选择器。

事件映射表

js 复制代码
// 事件映射表,左侧为 WEB 事件,右侧为 ``uni-app`` 对应事件
	{
		click: 'tap',
		touchstart: 'touchstart',
		touchmove: 'touchmove',
		touchcancel: 'touchcancel',
		touchend: 'touchend',
		tap: 'tap',
		longtap: 'longtap', //推荐使用longpress代替
		input: 'input',
		change: 'change',
		submit: 'submit',
		blur: 'blur',
		focus: 'focus',
		reset: 'reset',
		confirm: 'confirm',
		columnchange: 'columnchange',
		linechange: 'linechange',
		error: 'error',
		scrolltoupper: 'scrolltoupper',
		scrolltolower: 'scrolltolower',
		scroll: 'scroll'
	}

计算属性缓存 vs 方法

可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数

我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

props

props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。

选项 类型 说明
type StringNumberBooleanArrayObjectDateFunctionSymbol ,任何自定义构造函数、或上述内容组成的数组 会检查一个 prop 是否是给定的类型,否则抛出警告
default any 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。
required Boolean 定义该 prop 是否是必填项
validator Function 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 false 的值 (也就是验证失败),一个控制台警告将会被抛出
vue 复制代码
	<template>
		<view>
			<!-- 我是子组件componentA -->
			<view>{{age}}</view>
		</view>
	</template>
	<script>
		export default {
			props: {
				// 检测类型 + 其他验证
				age: {
					type: Number,
					default: 0,
					required: true,
					validator: function(value) {
						return value >= 0
					}
				}
			}
		}
	</script>
vue 复制代码
<template>
		<view>
			<!-- 我是父组件 -->
			<componentA :age="10"></componentA>
		</view>
	</template>

props单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

相关推荐
Stardep12 分钟前
算法2—八大常用排序算法(下)
c语言·数据结构·笔记·算法·排序算法·1024程序员节
lizz66628 分钟前
使用 Git 命令将本地项目上传到 GitLab
git·1024程序员节
榴莲千丞42 分钟前
第七章利用CSS和多媒体美化页面
前端·css·1024程序员节
千里马-horse1 小时前
在OpenCL 中输出CLinfo信息
开发语言·c++·算法·opencl·1024程序员节
Y.O.U..1 小时前
Linux-计算机网络-epoll的LT,ET模式
linux·服务器·计算机网络·算法·1024程序员节
板子小哥1 小时前
Lua语法基础全面剖析(中篇)
开发语言·嵌入式硬件·junit·单元测试·硬件工程·lua·1024程序员节
东方未明01082 小时前
C/C++(九)C语言与C++中的类型转换
c++·1024程序员节
马剑威(威哥爱编程)3 小时前
Java如何实现PDF转高质量图片
java·开发语言·pdf·1024程序员节
CoderJia程序员甲4 小时前
重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer
java·spring boot·reactor·1024程序员节
长潇若雪5 小时前
指针进阶(四)(C 语言)
c语言·开发语言·经验分享·1024程序员节