变化
文件变化:
以前是.html文件,现在是.vue文件
网络模型变化:
以前网页大多是b/s,服务端代码混合在页面里;
现在是c/s,前后端分离,通过js api(类似ajax的uni.request)获取json数据,把数据绑定在界面上渲染。
文件内代码架构变化:
以前一个html大节点,里面有script和style节点;
现在template是一级节点,用于写tag组件,script和style是并列的一级节点,也就是有3个一级节点。vue单文件组件规范
<template>
<view>
必须有一个view,且只能有一个根view。写所有内容。
</view>
</template>
<script>
export default {
data(){
}
}
</script>
<style>
</style>
外部文件引用方式变化:
以前通过script src、link href引入外部的js和css;
现是es6的写法,import引入外部的js模块(注意不是文件)或css
js要require进来,变成了对象。
在hello uni-app的common目录有一个工具类util.js,可以在hello uni-app中搜索这个例子查看。
<script>
var util = require('../../../common/util.js'); //require这个js模块
var formatedPlayTime = util.formatTime(playTime); //调用js模块的方法
</script>
而在这个util.js里,要把之前的function封装为对象的方法
function formatTime(time) {
return time;//这里没写逻辑
}
module.exports = {
formatTime: formatTime
}
还有一些高级的用法
var dateUtils = require('../../../common/util.js').dateUtils; //直接使用js模块的属性。在hello uni-app有示例
import * as echarts from '/components/echarts/echarts.simple.min.js'; //将js导入并重命名为echarts,然后使用echarts.来继续执行方法。在hello uni-app有示例
css外部文件导入
<style>
@import "./common/uni.css";
</style>
全局样式,在根目录下的app.vue里写入,每个页面都会加载app.vue里的样式。
另外,vue支持组件导入,可以更方便的封装一个包括界面、js、样式的库。
如下是导入一个角标的组件库,在页面上显示一个abc并且右上角有个数字角标1
<template>
<view>
<uni-badge text="abc" :inverted="true"></uni-badge><!--3.使用组件-->
</view>
</template>
<script>
import uniBadge from "../../../components/uni-badge.vue";//1.导入组件
export default {
data() {
return {
}
},
components: {
uniBadge //2.注册组件
}
}
</script>
如需要全局导入vue组件,每个页面都可以直接使用而不用引用和注册,在项目根目录下的main.js里处理。如下是hello uni-app里的例子。
//main.js
import pageHead from './components/page-head.vue' //导入
Vue.component('page-head', pageHead) //注册。注册后在每个vue的page页面里可以直接使用<page-head></page-head>组件。
组件/标签的变化:
- div 改成 view
- span、font 改成 text
- a 改成 navigator
- img 改成 image
- input还在,但type属性改成了confirmtype
- form、button、checkbox、radio、label、textarea、canvas、video这些还在。
- select 改成 pickerpicker
- iframe 改成 web-view
- ul、li没有了,都用 view替代
- audio不再推荐使用,改成api方式,背景音频api
除了改动外,新增了一批移动端常用的新组件
- scroll-view 可区域滚动视图容器
- swiper 可滑动区域视图容器
- icon 图标
- rich-text 富文本(不可执行js,但可渲染各种文字格式和图片)
- progress 进度条
- slider 滑块指示器
- switch 开关选择器
- camera 相机
- live-player 直播
- map 地图
- cover-view可覆盖原生组件的视图容器
cover-view需要多强调几句,uni-app的非h5端的video、map、canvas、textarea是原生组件,层级高于其他组件。如需覆盖原生组件,比如在map上加个遮罩,则需要使用cover-view组件
除了内置组件,还有很多开源的扩展组件,把常用操作都进行封装,DCloud建立了插件市场收录这些扩展组件,详见插件市场
js的变化:
js的变化,分为运行环境变化、数据绑定模式变化、api变化3部分。
标准js语法和api都支持,比如if、for、settimeout、indexOf等。
但浏览器专用的window、document、navigator、location对象,包括cookie等存储,只有在浏览器中才有,app和小程序都不支持。
可能有些人以为js等于浏览器里的js。其实js是ECMAScript组织管理的,浏览器中的js是w3c组织基于js规范补充了window、document、navigator、location等专用对象。
在uni-app的各个端中,除了h5端,其他端的js都运行在一个独立的v8引擎下,不是在浏览器中,所以浏览器的对象无法使用。如果你做过小程序开发,对此应当很了解。
这意味着依赖document的很多HTML的库,比如jqurey无法使用。
当然app和小程序支持web-view组件,里面可以加载标准HTML,这种页面仍然支持浏览器专用对象window、document、navigator、location。
- 以前的dom操作,改成vue的MVVM模式
现在前端趋势是去dom化,改用mvvm模式,更简洁的写法,大幅减少代码行数,同时差量渲染性能更好。
uni-app使用vue的数据绑定方式解决js和dom界面交互的问题。
如果你想改变某个dom元素的显示内容,比如一个view的显示文字:
以前是给view设id,然后js里通过选择器获取dom元素,进一步通过js进行赋值操作,修改dom元素的属性或值。 如下演示了一段代码,页面中有个显示的文字区和一个按钮,点击按钮后会修改文字区的值
<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>
如果你学过小程序的数据绑定,但不了解vue,要注意:
- 小程序的数据绑定参考了vue,但自己修改了一些。在uni-app中只支持标准的vue,不支持小程序的数据绑定语法
- 小程序里的setData在uni-app里并不存在,因为vue是自动双向数据绑定的。直接通过赋值方式修改数据,如果数据绑定到界面上,界面会自动更新渲染
- js api的变化
因为uni-app的api是参考小程序的,所以和浏览器的js api有很多不同,如
- alert,confirm 改成 uni.showmodel
- ajax 改成 uni.request
- cookie、session 没有了,local.storage 改成 uni.storage
uni-app的js api还有很多,但基本就是小程序的api,把wx.xxx改为uni.xxx即可。详见
uni-app在不同的端,支持条件编译,无限制的使用各端独有的api,条件编译
css的变化:
标准的css基本都是支持的。
选择器有2个变化:*选择器不支持;元素选择器里没有body,改为了page。微信小程序即是如此。
单位方面,px无法动态适应不同宽度的屏幕,rem无法用于nvue/weex。如果想使用根据屏幕宽度自适应的单位,推荐使用rpx,全端支持。
uni-app推荐使用flex布局,并默认就是flex布局,这个布局思路和传统流式布局有点区别。但flex的有趣在于,不管是什么技术都支持这种排版,web、小程序/快应用、weex/rn、原生的iOS、Android开发,全都支持flex。它是通吃所有端的新一代布局方案。相关教程请自行百度学习。
uni-app的vue文件里支持所有web排版方式,不管是流式还是flex。但nvue里,只支持flex,因为它在app端是使用原生排版引擎渲染的。
注意背景图和字体文件尽量不要大于40k。会影响性能。如果非要大于40k,需放到服务器侧远程引用或base64后引入,不能放到本地作为独立文件引用。在小程序里,其实小于40k的文件在css里也无法引用,uni-app编译器在编译时自动做了处理,把小于40k的文件编译为base64方式了。
工程结构和页面管理
uni-app的工程结构有单独的要求,详见
每个可显示的页面,都必须在 pages.json中注册。如果你开发过小程序,那么pages.json类似app.json。如果你熟悉vue,这里没有vue的路由,都是在pages.json里管理。
vue工程的首页一般是index.html或default.html,是在web server里配的。而uni-app的首页,是在pages.json里配的,page节点下第一个页面就是首页。一般在/pages/xx的目录下。
app和小程序中,为了提升体验,页面提供了原生的导航栏和底部tabbar,注意这些配置是在pages.json中做,而不是在vue页面里创建,但点击事件的监听在显示的vue页面中做。
在vue中,以前的js事件监听概念改为了生命周期概念。uni-app生命周期
如果你熟悉小程序开发的话,对比变化如下:
- 原来app.json被一拆为二。页面管理,被挪入了uni-app的pages.json;非页面管理,挪入manifest.json
- 原来的app.js和app.wxss被合并到了app.vue中
开发规范
为了实现多端兼容,综合考虑编译速度、运行性能等因素,uni-app 约定了如下开发规范:
- 页面文件遵循Vue 单文件组件 (SFC) 规范
- 组件标签靠近小程序规范,uni-app 组件规范
- 接口能力(JS API)靠近微信小程序规范,但需将前缀 wx 替换为 uni,uni-app接口规范
- 数据绑定及事件处理同 Vue.js 规范,同时补充了App及页面的生命周期
- 为兼容多端运行,建议使用flex布局进行开发
目录结构
一个uni-app工程,默认包含如下目录及文件:
┌─components uni-app组件目录
│ └─comp-a.vue 可复用的a组件
├─hybrid 存放本地网页的目录,
├─platforms 存放各平台专用页面的目录,
├─pages 业务页面文件存放的目录
│ ├─index
│ │ └─index.vue index页面
│ └─list
│ └─list.vue list页面
├─static 存放应用引用静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此
├─wxcomponents 存放小程序组件的目录,
├─main.js Vue初始化入口文件
├─App.vue 应用配置,用来配置App全局样式以及监听
├─manifest.json 配置应用名称、appid、logo、版本等打包信息
└─pages.json 配置页面路由、导航条、选项卡等页面类信息
Tips:
- static 下的 js 文件不会被编译,如果里有 es6 的代码,不经过转换直接运行,手机设备上会报错。
- css、less/scss 等资源同样不要放在 static 目录下,建议这些公用的资源放在 common 目录下。 HbuilderX1.9.0+ 支持在根目录创建 ext.json sitemap.json 文件。
资源路径:
++模板内引入静态资源:
template内引入静态资源,如image、video等标签的src属性时,可以使用相对路径或者绝对路径
++js文件引入:
js文件或script标签内(包括renderjs等)引入js文件时,可以使用相对路径和绝对路径
++css引入静态资源:
css文件或style标签内引入css文件时(scss、less文件同理),只能使用相对路径
注意:自HBuilderX 2.6.6-alpha起支持绝对路径引入静态资源,旧版本不支持此方式
路由:
uni-app页面路由为框架统一管理,开发者需要在pages.json里配置每个路由页面的路径及页面样式。类似小程序在app.json中配置页面路由一样。所以 uni-app 的路由用法与 Vue Router 不同,如仍希望采用 Vue Router 方式管理路由,可在插件市场搜索 Vue-Router。
路由跳转:
uni-app 有两种页面路由跳转方式:使用navigator组件跳转、调用API跳转。
配置
pages.json
pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。
condition
启动模式配置,仅开发期间生效,用于模拟直达页面场景,如小程序转发后,用户点击所打开的页面。
属性说明:
list说明:
注意: 在 App 里真机运行可直接打开配置的页面,微信开发者工具里需要手动改变编译模式.
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [
{
"name": "index", //模式名称
"path" : "pages/index/index",
"query": "interval=4000&autoplay=false" //启动参数,在页面的onLoad函数里面得到。
},
{
"name": "about", //模式名称
"path" : "pages/about/about",
"query": "" //启动参数,在页面的onLoad函数里面得到。
}
]
}
manifest.json
manifest.json 文件是应用的配置文件,用于指定应用的名称、图标、权限等。
package.json
通过在package.json文件中增加uni-app扩展节点,可实现自定义条件编译平台(如钉钉小程序、微信服务号等平台)。
vue.config.js
vue.config.js 是一个可选的配置文件,如果项目的根目录中存在这个文件,那么它会被自动加载,一般用于配置 webpack 等编译选项,具体规范参考:vue.config.js
uni.scss
uni.scss文件的用途是为了方便整体控制应用的风格。比如按钮颜色、边框风格,uni.scss文件里预置了一批scss变量预置。
uni.scss是一个特殊文件,在代码中无需 import 这个文件即可在scss代码中使用这里的样式变量。uni-app的编译器在webpack配置中特殊处理了这个uni.scss,使得每个scss文件都被注入这个uni.scss,达到全局可用的效果。如果开发者想要less、stylus的全局使用,需要在vue.config.js中自行配置webpack策略。
App.vue
App.vue是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面入口文件。但App.vue本身不是页面,这里不能编写视图元素。
这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData
main.js
main.js是uni-app的入口文件,主要作用是初始化vue实例、定义全局组件、使用需要的插件如vuex。
使用代码块直接创建组件模板
为提升开发效率,HBuilderX将 uni-app 常用代码封装成了以 u 开头的代码块,如在 template 标签内输入 ulist 回车,会自动生成如下代码:
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-list-cell-navigate uni-navigate-right" v-for="(item,index) in list" :key="index">
{{item.value}}
</view>
</view>
</view>
代码块分为Tag代码块、JS代码块,如在 script 标签内输入 uShowToast 回车,会自动生成如下代码:
uni.showToast({
title: '',
mask: false
duration: 1500
});
uni-app已支持代码块见下方列表:
Tag代码块:
- uButton
- uCheckbox
- uGrid:宫格,需引用uni ui
- uList:列表,需引用uni ui
- uListMedia
- uRadio
- uSwiper
几乎各种组件不管是内置组件还是uni ui的组件,均已封装为代码块,在HBuilderX的vue代码template区域中敲u,代码助手会提示所有可见列表。也可在HBuilderX菜单工具-代码块设置-vue代码块的左侧列表查阅所有。
除组件外,其他常用代码块包括:
- viewfor:生成一段带有v-for循环结构的视图代码块
- vbase:生成一段基本的vue代码结构
JS代码块:
uni api代码块:
- uRequest
- uGetLocation
- uShowToast
- uShowLoading
- uHideLoading
- uShowModal
- uShowActionSheet
- uNavigateTo
- uNavigateBack
- uRedirectTo
- uStartPullDownRefresh
- uStopPullDownRefresh
- uLogin
- uShare
- uPay
vue js代码块:
- vImport:导入文件
- ed:export default
- vData:输出 data( ) { return { } }
- vMethod:输出 methods:{}
- vComponents:输出 components: {}
其他常用js代码块:
- iff:简单if
- forr:for循环结构体
- fori:for循环结构体并包含i
- funn:函数
- funa:匿名函数
- rt:return true
- clog:输出:“console.log()”
- clogvar:增强的日志输出,可同时把变量的名字打印出来
- varcw:输出:“var currentWebview = this.mp.page.mp.page.getAppWebview()”
- ifios:iOS的平台判断
- ifAndroid:Android的平台判断
预置代码块不满足需求的话,可以自定义代码块,教程参考ask.dcloud.net.cn/article/359…
混合开发问题总结
uni-app和原生App混合开发问题:
首先务必确认uni-app和原生代码,谁是主谁是从的问题。
- 如你的应用是uni-app开发,需要扩展一些原生能力,请参考插件市场右上角的原生插件开发教程。
- 如你的App是原生开发的,部分功能栏目想通过uni-app实现,有2种方式
- 在原生App里集成uni小程序sdk,参考文档
- 如不想集成原生sdk,那就把uni-app代码发布成H5方式,在原生App里通过webview打开。
- 如果应用是uni-app开发为主,只是想离线打包,那么不应该使用uni小程序sdk,请在HBuilderX的发行菜单里点击离线打包。
- 另注意离线打包无法享受插件市场的付费原生插件,如有相关需求需自己进行原生插件开发,参考插件市场右上角的原生插件开发教程。
uni-app和原生小程序混合开发问题:
uni-app编译后的wxml代码没有可维护性,不便于整合到原生小程序里。如果想复用原生小程序的代码:
方式1:把原生小程序的代码变成组件,uni-app支持使用小程序wxml组件,参考
方式2:把原生小程序转换为uni-app源码,有各种转换工具,详见