1 js語法
? ?uni-app
的js API由標準ECMAScript的js API 和 uni 擴展 API 這兩部分組成。標準ECMAScript的js僅是最基礎的js。瀏覽器基于它擴展了window、document、navigator等對象。小程序也基于標準js擴展了各種wx.xx、my.xx、swan.xx的API。node也擴展了fs等模塊。uni-app基于ECMAScript擴展了uni對象,并且API命名與小程序保持兼容。
1.1?標準js和瀏覽器js的區別
? ?uni-app
的js代碼,h5端運行于瀏覽器中。非h5端(包含小程序和App),Android平臺運行在v8引擎中,iOS平臺運行在iOS自帶的jscore引擎中,都沒有運行在瀏覽器或webview里。非H5端,雖然不支持window、document、navigator等瀏覽器的js API,但也支持標準ECMAScript。請注意不要把瀏覽器里的js擴展對象等價于標準js。
????????所以uni-app的非H5端,一樣支持標準js,支持if、for等語法,支持字符串、數字、時間、布爾值、數組、自定義對象等變量類型及各種處理方法。僅僅是不支持window、document、navigator等瀏覽器專用對象。
1.2?ES6 支持
????????uni-app 在支持絕大部分 ES6 API 的同時,也支持了 ES7 的 await/async。ES6 API 的支持,詳見如下表格部分(x
?表示不支持,無特殊說明則表示支持):
String | iOS8 | iOS9 | iOS10 | Android |
---|---|---|---|---|
codePointAt | ||||
normalize | x | x | 僅支持 NFD/NFC | |
includes | ||||
startsWith | ||||
endsWith | ||||
repeat | ||||
String.fromCodePoint |
Array | iOS8 | iOS9 | iOS10 | Android |
---|---|---|---|---|
copyWithin | ||||
find | ||||
findIndex | ||||
fill | ||||
entries | ||||
keys | ||||
values | x | x | ||
includes | x | |||
Array.from | ||||
Array.of |
Number | iOS8 | iOS9 | iOS10 | Android |
---|---|---|---|---|
isFinite | ||||
isNaN | ||||
parseInt | ||||
parseFloat | ||||
isInteger | ||||
EPSILON | ||||
isSafeInteger |
Math | iOS8 | iOS9 | iOS10 | Android |
---|---|---|---|---|
trunc | ||||
sign | ||||
cbrt | ||||
clz32 | ||||
imul | ||||
fround | ||||
hypot | ||||
expm1 | ||||
log1p | ||||
log10 | ||||
log2 | ||||
sinh | ||||
cosh | ||||
tanh | ||||
asinh | ||||
acosh | ||||
atanh |
Object | iOS8 | iOS9 | iOS10 | Android |
---|---|---|---|---|
is | ||||
assign | ||||
getOwnPropertyDescriptor | ||||
keys | ||||
getOwnPropertyNames | ||||
getOwnPropertySymbols |
Other | iOS8 | iOS9 | iOS10 | Android<5 |
---|---|---|---|---|
Symbol | ||||
Set | ||||
Map | ||||
Proxy | x | x | x | |
Reflect | ||||
Promise |
????????默認不需要在微信工具里繼續開啟es6轉換。但如果用了微信的wxml自定義組件(wxcomponents目錄下),uni-app編譯器并不會處理這些文件中的es6代碼,需要去微信工具里開啟轉換。從HBuilderX調起微信工具時,如果發現工程下有wxcomponents目錄會自動配置微信工程打開es6轉換。
1.3?App端
????????在App端JS腳本運行在獨立的JS引擎中,vue頁面使用系統webview渲染,nvue頁面使用系統原生View渲染。
????????Android平臺
- JS腳本運行在獨立Google V8引擎中,版本與Chrome83一致,因此支持的語法與Android系統版本無關,即便是Android4.4也與Chrome83支持的語法一樣。
- vue頁面渲染在系統Webview中,受Android系統版本影響,在Android低端機上存在css瀏覽器兼容性問題,太新的css語法在低版本不支持。當然也可以使用x5等三方webview來拉齊實現。
????????iOS平臺
- JS腳本運行在iOS操作系統提供的JavaScriptCore 引擎,因此支持的語法與iOS系統有關,跟iOS系統的Safari瀏覽器一致。?
- vue頁面渲染在系統WKWebview中,受iOS系統版本影響,兼容性與iOS系統的Safari瀏覽器一致。
2 css語法
????????uni-app 有 vue 頁面、nvue 頁面、uvue頁面。?uni-app 的 css 與 web 的 css 基本一致。
- vue 頁面是 webview 渲染的
- app-nvue 頁面是原生渲染的,其樣式比 web 會限制更多
- app-uvue 頁面是原生渲染的,是 web 的css子集
2.1?css預處理器支持
????????uni-app 支持less、sass、scss、stylus等預處理器。sass的預處理器,早年使用node-sass,也就是vue2最初默認的編譯器。sass官方推出了dart-sass來替代。node-sass已經停維很久了。vue3默認使用的是dart-sass。DCloud推薦開發者盡快升級到vue3,改用dart-sass。
2.2?尺寸單位
? ?uni-app
?支持的通用 css 單位包括 px、rpx
- px 即屏幕像素
- rpx 即響應式 px,一種根據屏幕寬度自適應的動態單位。以 750 寬的屏幕為基準,750rpx 恰好為屏幕寬度。屏幕變寬,rpx 實際顯示效果會等比放大,但在 App(vue2 不含 nvue) 端和 H5(vue2) 端屏幕寬度達到 960px 時,默認將按照 375px 的屏幕寬度進行計算
????????vue 頁面支持下面這些普通 H5 單位,但在 nvue 里不支持:
- rem 根字體大小可以通過?page-meta 配置抖音小程序和飛書小程序:屏幕寬度/20、百度小程序:16px、支付寶小程序:50px
- vh viewpoint height,視窗高度,1vh 等于視窗高度的 1%
- vw viewpoint width,視窗寬度,1vw 等于視窗寬度的 1%
????????nvue 還不支持百分比單位。App 端,在 pages.json 里的 titleNView 或頁面里寫的 plus api 中涉及的單位,只支持 px。nvue 中,uni-app 模式可以使用 px 、rpx,表現與 vue 中基本一致,另外啟用?dynamicRpx 后可以適配屏幕大小動態變化。weex 模式目前遵循 weex 的單位,它的單位比較特殊:
- px:,以 750 寬的屏幕為基準動態計算的長度單位,與 vue 頁面中的 rpx 理念相同。(一定要注意 weex 模式的 px,和 vue 里的 px 邏輯不一樣。)
- wx:與設備屏幕寬度無關的長度單位,與 vue 頁面中的 px 理念相同
????????rpx
?詳細說明:設計師在提供設計圖時,一般只提供一個分辨率的圖。嚴格按設計圖標注的 px 做開發,在不同寬度的手機上界面很容易變形。而且主要是寬度變形。高度一般因為有滾動條,不容易出問題。由此,引發了較強的動態寬度單位需求。
????????微信小程序設計了 rpx 解決這個問題。uni-app
?在 App 端、H5 端都支持了?rpx
,并且可以配置不同屏幕寬度的計算方式rpx 是相對于基準寬度的單位,可以根據屏幕寬度進行自適應。uni-app
?規定屏幕基準寬度 750rpx。開發者可以通過設計稿基準寬度計算頁面元素 rpx 值,設計稿 1px 與框架樣式 1rpx 轉換公式如下:
設計稿 1px / 設計稿基準寬度 = 框架樣式 1rpx / 750rpx
????????換言之,頁面元素寬度在?uni-app
?中的寬度計算公式:
750 * 元素在設計稿中的寬度 / 設計稿基準寬度
舉例說明:
- 若設計稿寬度為 750px,元素 A 在設計稿上的寬度為 100px,那么元素 A 在?
uni-app
?里面的寬度應該設為:750 * 100 / 750
,結果為:100rpx。 - 若設計稿寬度為 640px,元素 A 在設計稿上的寬度為 100px,那么元素 A 在?
uni-app
?里面的寬度應該設為:750 * 100 / 640
,結果為:117rpx。 - 若設計稿寬度為 375px,元素 B 在設計稿上的寬度為 200px,那么元素 B 在?
uni-app
?里面的寬度應該設為:?750 * 200 / 375
,結果為:400rpx。
- 注意 rpx 是和寬度相關的單位,屏幕越寬,該值實際像素越大。如不想根據屏幕寬度縮放,則應該使用 px 單位。
- 如果開發者在字體或高度中也使用了 rpx ,那么需注意這樣的寫法意味著隨著屏幕變寬,字體會變大、高度會變大。如果你需要固定高度,則應該使用 px 。
- rpx 不支持動態橫豎屏切換計算,使用 rpx 建議鎖定屏幕方向
- 設計師可以用 iPhone6 作為視覺稿的標準。
- App 端,在 pages.json 里的 titleNView 或頁面里寫的 plus api 中涉及的單位,只支持 px,不支持 rpx。
- 早期 uni-app 提供了 upx ,目前已經推薦統一改為 rpx 了
2.3?樣式導入
????????使用@import
語句可以導入外聯樣式表,@import
后跟需要導入的外聯樣式表的相對路徑,用;
表示語句結束。
<style>@import "../../common/uni.css";.uni-card {box-shadow: none;}
</style>
2.4 內聯樣式
????????框架組件上支持使用 style、class 屬性來控制組件的樣式。
- style:靜態的樣式統一寫到 class 中。style 接收動態的樣式,在運行時會進行解析,請盡量避免將靜態的樣式寫進 style 中,以免影響渲染速度。
<view :style="{color:color}" />
- class:用于指定樣式規則,其屬性值是樣式規則中類選擇器名(樣式類名)的集合,樣式類名不需要帶上.,樣式類名之間用空格分隔。
<view class="normal_view" />
2.5?選擇器
選擇器 | 樣例 | 樣例描述 |
---|---|---|
.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
?節點,例如:
<!-- 設置頁面背景顏色,使用 scoped 會導致失效 -- >
page {background-color: #ccc;
}
-
web端可以使用
html
、body
、:root
等選擇器。由于頁面的css樣式隔離,且html節點并未添加data-xxx屬性,html
、:root
寫在頁面style內無效,只能寫在App.vue內。
2.6?全局樣式與局部樣式
????????定義在 App.vue 中的樣式為全局樣式,作用于每一個頁面。在 pages 目錄下 的 vue 文件中定義的樣式為局部樣式,只作用在對應的頁面,并會覆蓋 App.vue 中相同的選擇器。
- App.vue 中通過?
@import
?語句可以導入外聯樣式,一樣作用于每一個頁面。 - nvue 頁面暫不支持全局樣式
2.7?CSS 變量
????????uni-app 提供內置 CSS 變量
CSS 變量 | 描述 | App | 小程序 | H5 |
---|---|---|---|---|
--status-bar-height | 系統狀態欄高度 | 系統狀態欄高度、nvue 注意見下 | 25px | 0 |
--window-top | 內容區域距離頂部的距離 | 0 | 0 | NavigationBar 的高度 |
--window-bottom | 內容區域距離底部的距離 | 0 | 0 | TabBar 的高度 |
var(--status-bar-height)
?此變量在微信小程序環境為固定?25px
,在 App 里為手機實際狀態欄高度。- 當設置?
"navigationStyle":"custom"
?取消原生導航欄后,由于窗體為沉浸式,占據了狀態欄位置。此時可以使用一個高度為?var(--status-bar-height)
?的 view 放在頁面頂部,避免頁面內容出現在狀態欄。 - 由于在 H5 端,不存在原生導航欄和 tabbar,也是前端 div 模擬。如果設置了一個固定位置的居底 view,在小程序和 App 端是在 tabbar 上方,但在 H5 端會與 tabbar 重疊。此時可使用
--window-bottom
,不管在哪個端,都是固定在 tabbar 上方。 - 目前 nvue 在 App 端,還不支持?
--status-bar-height
變量,替代方案是在頁面 onLoad 時通過 uni.getSystemInfoSync().statusBarHeight 獲取狀態欄高度,然后通過 style 綁定方式給占位 view 設定高度。下方提供了示例代碼
????????快速書寫 css 變量的方法是:在 css 中敲 hei,在候選助手中即可看到 3 個 css 變量。
????????示例 1 - 普通頁面使用 css 變量:
<template><!-- HBuilderX 2.6.3+ 新增 page-meta --><page-meta><navigation-bar /></page-meta><view><view class="status_bar"><!-- 這里是狀態欄 --></view><view>狀態欄下的文字</view></view>
</template>
<style>.status_bar {height: var(--status-bar-height);width: 100%;}
</style>
<template><view><view class="toTop"><!-- 這里可以放一個向上箭頭,它距離底部tabbar上浮10px--></view></view>
</template>
<style>.toTop {bottom: calc(var(--window-bottom) + 10px);}
</style>
????????示例 2 - nvue 頁面獲取狀態欄高度
<template><view class="content"><view :style="{ height: iStatusBarHeight + 'px'}"></view></view>
</template><script>export default {data() {return {iStatusBarHeight: 0,};},onLoad() {this.iStatusBarHeight = uni.getSystemInfoSync().statusBarHeight;},};
</script>
2.8?固定值
? ?uni-app
?中以下組件的高度是固定的,不可修改:
組件 | 描述 | App | H5 |
---|---|---|---|
NavigationBar | 導航欄 | 44px | 44px |
TabBar | 底部選項卡 | HBuilderX 2.3.4 之前為 56px,2.3.4 起和 H5 調為一致,統一為 50px。(但可以自主更改高度) | 50px |
????????各小程序平臺,包括同小程序平臺的 iOS 和 Android 的高度也不一樣。
2.9?Flex 布局
????????為支持跨平臺,框架建議使用 Flex 布局。
2.10?背景圖片
? ?uni-app
?支持使用在 css 里設置背景圖片,使用方式與普通?web
?項目大體相同,但需要注意以下幾點:
- 支持 base64 格式圖片。
- 支持網絡路徑圖片。
- 小程序不支持在 css 中使用本地文件,包括本地的背景圖和字體文件。需以 base64 方式方可使用。
- 使用本地路徑背景圖片需注意:
- 為方便開發者,在背景圖片小于 40kb 時,
uni-app
?編譯到不支持本地背景圖的平臺時,會自動將其轉化為 base64 格式; - 圖片大于等于 40kb,會有性能問題,不建議使用太大的背景圖,如開發者必須使用,則需自己將其轉換為 base64 格式使用,或將其挪到服務器上,從網絡地址引用。
- 本地背景圖片的引用路徑推薦使用以 ~@ 開頭的絕對路徑。
- 為方便開發者,在背景圖片小于 40kb 時,
.test2 {background-image: url('~@/static/logo.png');
}
- 微信小程序不支持相對路徑(真機不支持,開發工具支持)
2.11?字體圖標
? ?uni-app
?支持使用字體圖標,使用方式與普通?web
?項目相同,需要注意以下幾點:
- 支持 base64 格式字體圖標。
- 支持網絡路徑字體圖標。
- 小程序不支持在 css 中使用本地文件,包括本地的背景圖和字體文件。需以 base64 方式方可使用。
- 網絡路徑必須加協議頭?
https
。 - 從?http://www.iconfont.cn?上拷貝的代碼,默認是沒加協議頭的。
- 從?http://www.iconfont.cn?上下載的字體文件,都是同名字體(字體名都叫 iconfont,安裝字體文件時可以看到),在 nvue 內使用時需要注意,此字體名重復可能會顯示不正常,可以使用工具修改。
- 使用本地路徑圖標字體需注意:
- 為方便開發者,在字體文件小于 40kb 時,
uni-app
?會自動將其轉化為 base64 格式; - 字體文件大于等于 40kb,仍轉換為 base64 方式使用的話可能有性能問題,如開發者必須使用,則需自己將其轉換為 base64 格式使用,或將其挪到服務器上,從網絡地址引用;
- 字體文件的引用路徑推薦使用以 ~@ 開頭的絕對路徑。
- 為方便開發者,在字體文件小于 40kb 時,
@font-face {font-family: test1-icon;src: url('~@/static/iconfont.ttf');
}
? ?nvue
中不可直接使用 css 的方式引入字體文件,需要使用以下方式在 js 內引入。nvue 內不支持本地路徑引入字體,請使用網絡鏈接或者base64
形式。src
字段的url
的括號內一定要使用單引號。
var domModule = weex.requireModule('dom');
domModule.addRule('fontFace', {fontFamily: 'fontFamilyName',src: "url('https://...')",
});
<template><view><view><text class="test"></text><text class="test"></text><text class="test"></text></view></view>
</template>
<style>@font-face {font-family: 'iconfont';src: url('https://at.alicdn.com/t/font_865816_17gjspmmrkti.ttf') format('truetype');}.test {font-family: iconfont;margin-left: 20rpx;}
</style>