如果你平时用Vue写H5项目比较多,然后突然有一天公司要你用uni-app来同时开发H5和小程序(甚至App),而你却对uni-app不熟悉,那么这篇文章或许适合你。
下面我将从以下几个维度出发,总结uni-app开发与Vue开发的不同之处。
① 项目搭建
② 配置文件
③ 内置组件
④ 数据请求
⑤ 其他
一、项目搭建
uni-app项目搭建有两种方式,一种是通过vue-cli命令行方式,一种是通过HBuilderX可视化界面方式,新手推荐直接使用第二种方式,简单快捷,下载按照好HBuilderX开发工具后,点击顶部工具栏里的文件 -> 新建 -> 项目(快捷键Ctrl+N)后即可创建。
HBuilderX下载链接: https://www.dcloud.io/hbuilderx.html
二、配置文件
uni-app配置文件主要有三个:manifest.json、pages.json和package.json。
manifest.json是应用的配置文件,用于指定应用的名称、图标、权限等。在开发小程序时需要添加以下配置选项:
"mp-weixin": {
"appid": "", // 此处须填写小程序的appid,否则无法用真机预览
"lazyCodeLoading": "requiredComponents" // 组件按需注入
}
pages.json文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。在uni-app项目中无需使用vue-router,页面路由就是在pages.json文件中配置的。
package.json文件通常是用于配置安装依赖的,这点与Vue相同。除此之外,我们还可以在其中配置扩展web和小程序平台,具体配置方法详见 → https://uniapp.dcloud.net.cn/collocation/package.html
三、内置组件
本文列举几个常见的与H5开发不同的内置组件,更多相关内容请直接到uni-app官网查看 → https://uniapp.dcloud.net.cn/component/view.html
1. <navigator>
<navigator>
相当于Vue项目中的<router-view>
,但使用方式略有不同。
<navigator url="/pages/home/index">首页</navigator>
url
属性值必须是在pages.json中pages
里配置好的,如果需要传递参数,接收该参数的页面中需要通过生命周期中的onLoad
钩子函数来接收,例如:
<navigator url="/pages/home/index?id=1">首页</navigator>
export default {
onLoad: function (option) { //option为object类型,会序列化上个页面传递的参数
console.log(option.id); //打印出上个页面传递的参数。
}
}
2. <scroll-view>
在H5中,如果要实现页面内的局部滚动,我们可以直接使用CSS属性overflow: auto
即可实现,可小程序中并不支持,所以这时我们就需要使用<scroll-view>
来替代。不过需要注意的是,如果是纵向滚动,我们需要给<scroll-view>
添加scroll-y
属性,并给其CSS添加固定高度,例如:
<scroll-view scroll-y>
滚动部分
</scroll-view>
/*具体高度根据实际项目而定*/
height: 200px;
* 返回顶部问题
<scroll-view>
有个scroll-top
属性,我们可以通过设置该属性值,让其滚动到指定位置(比如返回顶部)。但是当我们手动滑动页面让<scroll-view>
滚动时,scroll-top
属性值并不会随之改变,这时候我们再次设置与之前相同的scroll-top
属性值后,<scroll-view>
不会发生滚动。例如:
<scroll-view scroll-y :scroll-top="scrollTop"></scroll-view>
export default {
data() {
return {
scrollTop: 0
}
},
methods: {
goTop: function(e) { // 返回顶部
this.scrollTop = 0; // 无效
}
}
}
对于此问题,uni-app官方给出的方案是,在scroll
事件执行的方法中,将滚动条位置保存下来,之后当我们执行返回顶部方法时,先将scrollTop
设置为保存下来的该位置,然后再将scrollTop
设置为0。具体代码如下:
<scroll-view scroll-y="true" :scroll-top="scrollTop" @scroll="scroll"></scroll-view>
export default {
data() {
return {
scrollTop: 0,
old: {
scrollTop: 0
}
}
},
methods: {
scroll: function(e) {
this.old.scrollTop = e.detail.scrollTop
},
goTop: function(e) {
this.scrollTop = this.old.scrollTop
this.$nextTick(function() {
this.scrollTop = 0
});
}
}
}
此方法固然是可以解决问题的,但是看起来并不够简单直观。首先我们要知道,产生该问题的主要问题在于,当重复设置组件某些属性为相同的值时,不会同步到view层,所以我们只需要先改变初始值为一个非0值,再将该值设置为0即可。例如:
export default {
data() {
return {
scrollTop: 0
}
},
methods: {
goTop: function(e) { // 返回顶部
this.scrollTop = 0.01; // 设置为非0且接近于0的值
this.$nextTick(() => {
this.scrollTop = 0;
});
}
}
}
3. <swiper>
在小程序中没有window
和document
等对象,所以不能使用类似Swiper.js这样的JS插件,而uni-app自身也提供了<swiper>
组件,我们需要开发轮播图功能时就可以直接拿来使用即可。
4. <image>
在H5中加载图片需要用到<img>
标签,而uni-app中需要用<image>
组件来实现,并且它默认是有宽高的(宽度 320px、高度 240px),如果要让图片高度自适应的话,需要加上mode="widthFix"
属性。
四、数据请求
数据请求我们可以使用axios来做数据拦截,但是具体请求时还是需要用uni-app提供的uni.request()
API,例如:
// request.js
import axios from 'axios'
import qs from 'qs'
// 创建axios实例
const service = axios.create();
const baseUrl = ''; // 此处填写接口相对URL,用于拼接在url前面
service.defaults.timeout = 30000;
service.defaults.baseURL = baseUrl;
axios.defaults.adapter = function(config) {
return new Promise((resolve, reject) => {
let data = config.method === 'get' ? config.params : config.data;
uni.request({
url: baseUrl + config.url,
method: config.method || 'get',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
data: data,
success: (res) => {
return resolve(res)
},
fail: (err) => {
return reject(err)
}
})
})
};
// request拦截器
service.interceptors.request.use(
config => {
uni.showLoading({
title: '加载中'
});
if (config.method === 'post') {
config.data = qs.stringify(config.data);
}
return config;
},
error => {
console.log(error)
Promise.reject(error)
}
);
// response 拦截器
service.interceptors.response.use(
response => {
uni.hideLoading();
const res = response.data;
if (res.code === 500) {
uni.showToast({
icon: 'none',
title: res.msg
});
return Promise.reject('error')
} else {
return response.data
}
},
error => {
uni.showToast({
icon: 'none',
title: '未知错误'
});
return Promise.reject(error)
}
)
export default service;
// index.js
import request from './request.js';
// 请求列表
export function getList(data) {
return request({
url: '/list',
params: data
});
}
五、其他
1. 自定义组件
我们在引入自定义组件时,需要直接在模板页面中引入,不能在另外的js文件引入,否则在小程序中自定义组件将无法在页面中成功渲染。
2. 样式
小程序不支持在 css 中使用本地文件,包括本地的背景图和字体文件。我们可以使用网络文件或base64替代。
3. 弹层提示
弹层提示在项目中使用频率非常高,就是像“加载中”、“提交成功”之类的提示,弹出提示后几秒钟就自动隐藏。
在使用Vue开发H5时,对于这样的弹层提示,我们通常都是自己封装组件,然后通过js来调用。但是在uni-app中,则可以直接使用uni.showLoading()
和uni.showToast()
来实现这样的弹层提示,非常方便。为了更加简洁,我们还可以在此基础上再封装一层,例如:
// 定义全局方法便于调用
Vue.prototype.$message = (msg, icon) => {
uni.showToast({
title: msg,
icon: icon ? icon : 'none'
})
}
this.$message('请输入手机号');
this.$message('提交成功', 'success');