uni-app开发指南

如果你平时用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>

在小程序中没有windowdocument等对象,所以不能使用类似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');
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容