Uni-app框架(小程序开发) 笔记

Uni-app框架(小程序开发)

一、安装以及配置

  • 下载Hbuilder X标准版,下载插件,scss/sass编译、uni-app编译、内置浏览器、内置终端。查看更多
  • 下载微信开发者工具,安装后,点设置=》安全=》开启服务端口。查看更多
  • 登陆微信开发者工具,在微信公众平台上扫码登陆获得测试号的appID
  • 第一次使用,需要配置开发工具的相关路径。点击工具栏的运行 -> 运行到小程序模拟器 -> 运行设置,配置相应小程序开发者工具的路径。

  • 在HbuilderX打开已有项目,点击运行->运行到小程序模拟器-微信开发者工具,可以同步更新

二、uni-app是什么

  • 基于Vue.js开发的前端应用框架
  • 开发一套代码,能同时发布到iOS. Android、 H5、以及 各种小程序平台。
  • 支持通过npm安装第三方包

三、创建运行以及打包

3.1、创建uni-app

在点击工具栏里的文件 -> 新建 -> 项目:

选择uni-app类型,输入工程名,选择模板,点击创建,即可成功创建。

3.2、运行uni-app

此处只针对微信小程序开发,点击运行->运行到小程序模拟器-微信开发者工具

3.3、打包uni-app

此处只针对微信小程序发布

  • 申请微信小程序AppID,参考:微信教程

  • 在HBuilderX中顶部菜单依次点击 "发行" => "小程序-微信",输入小程序名称和appid点击发行即可

四、框架介绍

4.1、目录结构

 ┌─components uni-app组件目录

│ └─comp-a.vue 可复用的a组件

├─hybrid 存放本地网页的目录,详见

├─pages 业务页面文件存放的目录

│ ├─index

│ │ └─index.vue index页面

│ └─list

│ └─list.vue list页面

├─static 存放应用引用静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此

├─wxcomponents 存放小程序组件的目录,详见

├─main.js Vue初始化入口文件

├─App.vue 应用配置,用来配置App全局样式以及监听 应用生命周期

├─manifest.json 配置应用名称、appid、logo、版本等打包信息,详见

└─pages.json 配置页面路由、导航条、选项卡等页面类信息,详见

4.2、开发规范

为了实现多端兼容,综合考虑编译速度,运行性能等因素,uni-app 约定了如下开发规范:

为兼容多端运行,建议使用 flex 布局进行开发

4.2.1 页面文件向导Vue单文件组件(SFC)规范

.vue 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 <template><script><style>,还允许添加可选的自定义块:

<template>

<view>

注意必须有一个view,且只能有一个根view。所有内容写在这个view下面。

</view>

</template>

<script>

export default {

}

</script>

<style>

</style>
  • 每个 .vue 文件最多包含一个 <template> 块。 <template> 内最多包含一个 <view> 标签
  • 每个 .vue 文件最多包含一个 <script> 块。
  • 一个 .vue文件可以包含多个 <style>标签
  • 任何匹配 .css文件 (或通过它的 lang特性指定的扩展名) 的 webpack 规则都将会运用到这个 <style>块的内容中

4.2.2 组件标签靠近小程序规范,详见 uni-app 组件规范

  • <view>标签在uniapp中的含义与标准html中的<div>标签能力相当

  • 不能直接使用html中的img,你应该使用uniapp的组件标签image

  • <view>标签的属性是变量时,属性前面需增加:冒号前缀,属性值仍使用引号包裹,但引号里不是字符串,而是js。

4.2.3 互连能力(JS API)靠近微信小程序规范

  • 需要将 wx替换为 uni,详见 uni-app 接口规范
  • 自定义后台api,和react项目一样,统一定义

4.2.4 css样式规范

uni-app 支持的通用 css 单位包括 px、rpx

  • rpx 即响应式 px,一种根据屏幕宽度自适应的动态单位。以 750 宽的屏幕为基准,750rpx 恰好为屏幕宽度。屏幕变宽,rpx 实际显示效果会等比放大,但在 App(vue2 不含 nvue) 端和 H5(vue2) 端屏幕宽度达到 960px 时,默认将按照 375px 的屏幕宽度进行计算,具体配置参考:rpx 计算配置
  • 计算公式:

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

750 * 元素在设计稿中的宽度 / 设计稿基准宽度

五、页面与page.json

pages

  • 每次新建页面,均需在pages.json中配置pages列表;未在pages.json -> pages 中配置的页面,uni-app会在编译阶段进行忽略;
  • 删除页面时,需做两件工作:删除.vue文件;删除pages.json -> pages列表项中的配置;
  • uni-app会将pages.json -> pages配置项中的第一个页面,作为当前工程的首页(启动页)。

tabBar

  • tabBar 中的 list 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序;
  • tabbar 的页面展现过一次后就保留在内存中,再次切换 tabbar 页面,只会触发每个页面的onShow,不会再触发onLoad;

  • 代码跳转到 tabbar 页面,api只能使用uni.switchTab (opens new window),不能使用uni.navigateTo、uni.redirectTo;

subPackages

  • 分包加载配置,此配置为小程序的分包加载机制。

  • 微信小程序每个分包的大小是2M,总体积一共不能超过20M。

  • 主包放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本

六、vue语法

插值

<template>
    <view>
      <view>{{ number + 1 }}</view>
      <view>{{ ok ? 'YES' : 'NO' }}</view>
      <!-- 把一个字符串分割成字符串数组,颠倒其元素的顺序,把数组中的所有元素放入一个字符串 -->
      <view>{{ message.split('').reverse().join('') }}</view>
    </view>
</template>
<script>
  export default {
    data() {
      return {
        number:1,
        ok:true,
        message: 'Hello Vue!'
      }
    }
  }
</script>

指令

v-bind

  • v-bind缩写为‘ : ’
  • 可以用修饰符指定不同的绑定类型。
<image v-bind:src="imgUrl"></image>
<!-- 缩写 -->
<image :src="imgUrl"></image>

v-on

v-on 指令,它用于监听 DOM 事件。v-on缩写为‘ @ ’,下文简称为 @事件

事件映射表

v-once

只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。

v-html

条件渲染

v-if和v-else

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。 使用 v-else 指令来表示 v-if 的“else 块”。

<template>
        <view>
                <view v-if="type === 'A'">A</view>
                <view v-else-if="type === 'B'">
                        B
                </view>
                <view v-else-if="type === 'C'">
                        C
                </view>
                <view v-else>其他</view>
        </view>
</template>
<script>
        export default {
                data() {
                        return {
                                type:'B'
                        }
                }
        }
</script>

v-show

v-show 是一个根据条件展示元素选项的指令 。用法大致和 v-if 一样

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性的 display

列表渲染

在 v-for 里使用数组

  • v-for 指令需要使用 item in list形式的特殊语法,其中 list是源数据数组,而 item 则是被迭代的数组元素的别名。
    • 第一个参数 item 则是被迭代的数组元素的别名。
    • 第二个参数,即当前项的索引 index ,是可选的。

在 v-for 里使用对象

  • 第一个参数 value 是被迭代的对象元素的属性值。
  • 第二个参数为 property 名称 (也就是键名)。
  • 第三个参数作为索引。
<template>
        <view>
                <view v-for="(arr, name, index) in object">
                        <view class="name">
                                {{name}}
                        </view>
                        <view v-for="(item, i) in arr">
                                {{item.label}}:{{item.value}}
                        </view>
                </view>
        </view>
</template>
<script>
        export default {
                data() {
                        return {
                                object: {
                                        title: [
                                                {label: '111', value: '11'}
                                                {label: '222', value: '22'}
                                        ],
                                        name: [],
                                        time: []
                                }
                        }
                }
        }
</script>

七、生命周期

5.1、页面生命周期

函数名说明平台差异说明
onLoad监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例
onShow监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
onReady监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发
onHide监听页面隐藏
onUnload监听页面卸载
onResize监听窗口尺寸变化App、微信小程序、快手小程序
onPullDownRefresh监听用户下拉动作,一般用于下拉刷新,参考示例
onReachBottom页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项
onTabItemTap点击 tab 时触发,参数为Object,具体见下方注意事项微信小程序、QQ小程序、支付宝小程序、百度小程序、H5、App、快手小程序、京东小程序
onShareAppMessage用户点击右上角分享微信小程序、QQ小程序、支付宝小程序、字节小程序、飞书小程序、快手小程序、京东小程序
onPageScroll监听页面滚动,参数为Objectnvue暂不支持
onShareTimeline监听用户点击右上角转发到朋友圈微信小程序
onAddToFavorites监听用户点击右上角收藏微信小程序

onPullDownRefresh

  • 需要在 pages.json 里,找到的当前页面的pages节点,并在 style 选项中开启 enablePullDownRefresh
  • 需要在onLoad生命周期内开启uni.startPullDownRefresh
  • 当处理完数据刷新后,uni.stopPullDownRefresh 可以停止当前页面的下拉刷新。

5.2、组件生命周期

函数名说明
onLaunch当uni-app初始化完成时触发(局部只触发一次)
onOpen当uni-app启动,或从后台进入前台显示
onHide当uni-app从前台进入后台
onError当uni-app报错时触发
onUniNViewMessage对nvue页面发送的数据进行监听,可参考 nvue 向 vue 通讯
onUnhandledRejection对未处理的 Promise 拒绝事件监听函数(2.8.1+)
onPageNotFound页面不存在监听函数
onThemeChange监听系统主题变化
  • 应用生命周期仅可在 App.vue 中监听,在其他页面监听无效。
  • onlaunch 里进行页面调整,如遇白屏报错,请参考 https://ask.dcloud.net.cn/article/35942

八、路由

  • uni-app页面路由为框架统一管理,开发者需要在pages.json里配置每个路由页面的路径和页面样式。
  • uni-app有两种页面路由重定向方式:使用导航器组件扩展,调用API重定向。

页面栈

框架以栈的形式管理当前所有页面,当发生路由切换的时候,页面栈的表现如下:

路由方式页面栈表现触发时机
初始化新页面入栈uni-app:的第一个页面
:新页面新页面入栈调用API uni.navigateTo ,使用组件 <navigator open-type =“ navigate” />
页面重启当前页面出栈,新页面入栈调用API uni.redirectTo ,使用组件 <navigator open-type =“ redirectTo” />
页面返回页面不断出栈,直到目标返回页调用API uni.navigateBack ,使用组件 <navigator open-type =“ navigateBack” /> ,用户按左上角返回按钮,安卓用户点击物理后退键
标签切换页面全部出栈,只留下新的标签页面调用API uni.switchTab ,使用组件 <navigator open-type =“ switchTab” /> ,用户切换Tab
重加载页面全部出栈,只留下新的页面调用API uni.reLaunch ,使用组件 <navigator open-type =“ reLaunch” />

九、组件

scroll-view

可滚动视图区域。用于区域滚动。

性名类型默认值说明
scroll-xBooleanFALSE允许横向滚动
scroll-yBooleanFALSE允许纵向滚动
scroll-topNumber/String设置竖向滚动条位置
scroll-leftNumber/String设置横向滚动条位置
scroll-into-viewString值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素
show-scrollbarBooleanFALSE控制是否出现滚动条
refresher-enabledBooleanFALSE开启自定义下拉刷新
refresher-thresholdNumber45设置自定义下拉刷新阈值
refresher-default-styleString"black"设置自定义下拉刷新默认样式,支持设置 black,white,none,none 表示不使用默认样式
refresher-backgroundString"#FFF"设置自定义下拉刷新区域背景颜色
refresher-triggeredBooleanFALSE设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
enable-flexBooleanFALSE启用 flexbox 布局。开启后,当前节点声明了 display: flex 就会成为 flex container,并作用于其孩子节点。
scroll-anchoringBooleanFALSE开启 scroll anchoring 特性,即控制滚动位置不随内容变化而抖动,仅在 iOS 下生效,安卓下可参考 CSS overflow-anchor 属性。
@scrolltoupperEventHandle滚动到顶部/左边,会触发 scrolltoupper 事件
@scrolltolowerEventHandle滚动到底部/右边,会触发 scrolltolower 事件
@scrollEventHandle滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}
@refresherpullingEventHandle自定义下拉刷新控件被下拉
@refresherrefreshEventHandle自定义下拉刷新被触发
@refresherrestoreEventHandle自定义下拉刷新被复位
@refresherabortEventHandle自定义下拉刷新被中止

map

<template>
<map class="page-map" :latitude="latitude" :longitude="longitude" :polygons="polygons"
 :polyline="polylines" :markers="markers" scale="11.5" @markertap="tapMarker"
 @tap="tapMap" :circles="circles">
                        <my-callout slot="callout" :points="markers" rich="true"
                            :cutomContentStyle="cutomContentStyle" :markerDetail="markerDetail">

                            <!-- <my-callout slot="callout" :points="covers_fanglaopaishui"> -->
                        </my-callout>
</map>
</template>
<script>
        export default {
                data() {
                        return {
                                polygons: [],
                                polylines: [],
                                circles: [],
                                markers: [],
                                longitude: 120.0,
                                latitude: 30.0
                        }
                },
                methods: {
                    tapMarker(){
                        console.log("点位点击事件")
                    },
                    tapMap(){
                       console.log("地图点击事件")
                    }
                }
        }
</script>
地图服务商说明
地图服务商AppH5微信小程序
高德
Goolge3.4+3.2.10+
腾讯

注意

  • <map> 组件的宽/高推荐写直接量,比如:750rpx,不要设置百分比值。
  • 谷歌地图使用 wgs84 坐标,其他地图使用 gcj02 坐标,用错坐标类型会显示偏移
  • 原生map组件没有提供线和面覆盖物的点击事件监听,需要自行处理。多边形判断如下:
//判断是否在多边形内
windingNumber(p, poly) {
 var px = p.latitude,
 py = p.longitude,
 sum = 0
            for (var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {
                var sx = poly[i].latitude,
                    sy = poly[i].longitude,
                    tx = poly[j].latitude,
                    ty = poly[j].longitude

                // 点与多边形顶点重合或在多边形的边上
                if ((sx - px) * (px - tx) >= 0 && (sy - py) * (py - ty) >= 0 && (px - sx) * (ty - sy) === (py - sy) * (
                        tx - sx)) {
                    return 'on'
                }

                // 点与相邻顶点连线的夹角
                var angle = Math.atan2(sy - py, sx - px) - Math.atan2(ty - py, tx - px)

                // 确保夹角不超出取值范围(-π 到 π)
                if (angle >= Math.PI) {
                    angle = angle - Math.PI * 2
                } else if (angle <= -Math.PI) {
                    angle = angle + Math.PI * 2
                }

                sum += angle
            }

            // 计算回转数并判断点和多边形的几何关系
            return Math.round(sum / Math.PI) === 0 ? 'out' : 'in'
}

chart图表

echarts引入
  1. 引入npm install echarts mpvue-echarts
  2. ECharts 在线构建 定制 echarts 的 js 文件
  3. 新建 common 文件夹,将定制文件放在 common 下
  4. 将node_modules下面的mpvue-echarts->src复制到components,如下图
  5. 示例如下
<template>
 <view>
 <view class="echarts-wrap">
 <my-echarts id="main" ref="mapChart" :echarts="echarts"
 :option="mapOption" v-if="mapOption.series" :onInit="initChart" />
 </view>
 </view>
</template>
<script>
 import * as echarts from '@/common/echarts.min.js';
 import myEcharts from '@/components/mpvue-echarts/src/echarts.vue';
export default {
    components: {
        myEcharts
    },
    data() {
        return {
            echarts,
            mapOption: {},
        }
    },
    onLoad() {
        this.loadOption();
    },
    methods: {
        loadOption(){
            this. mapOption = {
                throttleTouch: true,
                title: {
                    text: 'ECharts 入门示例'
                },
                tooltip: {},
                legend: {
                    data: ['销量']
                },
                xAxis: {
                    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
                },
                yAxis: {},
                series: [{
                    name: '销量',
                    type: 'bar',
                    data: [5, 20, 36, 10, 10, 20]
                }]
            }; // ECharts 配置项
        },
        initChart(canvas, width, height, option) {
            console.log('图标', canvas);
            let chart = null
            chart = echarts.init(canvas, null, {
                width: width,
                height: height
            });

            chart.setOption(option);

            return chart; // 返回 chart 后可以自动绑定触摸操作
        }
    }
}
</script>
<style>
 .echarts-wrap {
 width: 100%;
 height: 300px;
 }
</style>
常见错误

报错:this.echarts.setCanvasCreator is not a function 的解决办法

这个错误是由于 prors不能传递方法(之前是可以的,不知道是平台的差异还是版本的差异);
解决办法 将echarts.js 直接导入到echarts.vue 中.

还有uni api 有变动 echarts.vue 中有两处需要修改

createCanvasContext() 第二个参数传入当前组建 即this,
createSelectorQuery() 后面加上调用 in(this).

echarts.vue完整代码如下

u-charts引入
  1. 首先到gitee上把项目代码下载下来,下载地址
  2. u-charts.js放在common下或者components下
  3. 使用示例:
<template>
        <view class="cw-container">
                <canvas canvas-id="canvasLineA" id="canvasLineA" class="charts" width="640"
                        height="640" @touchstart="touchLineA"></canvas>
        </view>
</template>

<script>
        import uCharts from '@/components/u-charts/u-charts.js';
        var canvaLineA = null;
        export default {
                data() {
                        return {
                        }
                },
                onLoad(res) {
                        this.loadData();
                },
                methods: {
                        loadData() {
                                let LineA = {
                                        categories: ['潮汐', '潮汐2', '潮汐3'],
                                        series: []
                                };
                                LineA.series = [{ //潮汐
                                                color: "#3296FA",
                                                data: [2,4,54,5]
                                        }, {
                                                color: "#47B024",
                                                data: [2,4,63,2]
                                        }, {
                                                color: "#1E0BFB",
                                                data: [6,4,3,4]
                                        }
                                ];
                                this.showLineA("canvasLineA", LineA);
                        },
                        showLineA(canvasId, chartData) {
                                canvaLineA = new uCharts({
                                        $this: this,
                                        canvasId: canvasId,
                                        type: 'line',
                                        fontSize: 11,
                                        padding: [15, 1, 0, 10],
                                        legend: {
                                                show: true,
                                                padding: 5,
                                                lineHeight: 11,
                                                margin: 0,
                                                position: 'top',
                                        },
                                        dataLabel: false,
                                        dataPointShape: true,
                                        background: '#FFFFFF',
                                        pixelRatio: 1,
                                        categories: chartData.categories,
                                        series: chartData.series,
                                        animation: true,
                                        xAxis: {
                                                disableGrid: true,
                                                type: 'grid',
                                                gridColor: '#CCCCCC', //竖着的虚线
                                                gridType: 'dash',
                                                dashLength: 8,
                                                // rotateLabel: true,
                                                labelCount: 7,
                                        },
                                        yAxis: {
                                                gridType: 'dash',
                                                gridColor: '#CCCCCC', //横着的虚线
                                                dashLength: 8,
                                                splitNumber: 5,
                                                format: (val) => {
                                                        return val.toFixed(0)
                                                }, //左侧数值
                                                min: 0,
                                                max: 10,
                                        },
                                        extra: {
                                                line: {
                                                        type: 'curve'
                                                }
                                        }
                                });
                        },
                        touchLineA(e) {
                                canvaLineA.touchLegend(e);
                                canvaLineA.showToolTip(e, {
                                        format: function(item, category, key) {
                                                return category + item.name + ':' + item.data
                                        }
                                });
                        }
                }
        }
</script>

<style scoped lang="scss">
        .cw-container {
                height: 100%;
                width: 100%;
                background: #F6F6F6;
                padding: 16rpx 0;
        }

        .qiun-charts {
                width: 640rpx;
                height: 500rpx;
                background-color: #FFFFFF;
        }
</style>

缺点:功能相对echarts较少

优点:体量小,加载快

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值