阅读 311

当我会 vue 的情况下怎么玩 小程序

前言

  • 前端现在的东西越来越多,基础的有 css html javaScript,三大框架 vue react angular,还有今天要讲的一个东西,小程序
  • 小程序有很多,各大平台都推出自己的小程序应用,而最被人们熟悉的是 微信小程序 如今也成为了前端必备技能之一,当然不必害怕这么多的API怎么办,都差不多~
  • 在我的认知里面小程序是什么?有什么用?他在现在web越来越为市场作为应用的环境里提供了一个很好的平台,还扩充了一些只有程序才有的功能,例如录音,摄像头的调用,它实现了不需要下载安装既可使用的应用
  • 都说会三大框架学小程序很简单,就能写,事实如何?这篇文章,我以一个已经熟知 Vue 框架的视角,去看看,小程序到底有什么不同,我们到底能不能写出小程序
  • 此文章只带大家粗略的入门,小程序的坑还是挺多的,建议开发时多查查文档~

预备工作

  • 我将会使用 微信开发者工具VsCode 编程
  • 微信开发者工具
  • vsCode: 小程序开发助手
  • 账号的申请等官方已经为我们准备了详细的文档,这里就不赘述了,当然,一开始我们也可以使用测试号尝试

结构目录

结构传统web微信小程序Vue
结构htmlwxml<template>
样式csswxss<style>
逻辑JavaScriptJavaScript<script>
配置jsonjson
  • pages 内为页面内容,以从上到下的整个大框为一个页面的标准,对比 Vue 的目录结构一般为 views
  • pages 外的部分,为公共样式、逻辑、配置
  • project.config.json:项目的配置文件 appid等信息
  • sitemap.json:微信索引配置文件 - 配置小程序及其页面是否允许被微信索引

配置文件

app.json

pages

  • 页面内容数组,我们可以把它看为是小程序 router,与 Vue 相比,pages 对应 views(目录名),而非 components(目录名)
  • 如果我们需要新增一个页面,可在 pages 内增加一个 路径及页面名称信息,则微信开发者工具会自动新增该文件
  • [0] 下为一打开小程序进入的页面

window

  • 定义所有页面的顶部背景颜色,文字颜色定义等
  • 参数与 pages 目录下的页面 json 类似,app.json 为全局配置,请看 pages/xxx.json

tabbar

  • 导航组件

  • list - 导航信息数组

// 最少两个
{
  "list": [{
  "pagePath": "pages/index/index", // pages 内的 路径
  "text": "首页", // 文字描述
  "iconPath": "assets/index.png", // 未选中图标
  "selectedIconPath": "assets/index_select.png" // 选中后图标
  },{
  "pagePath": "pages/my/index",
  "text": "我的",
  "iconPath": "assets/my.png",
  "selectedIconPath": "assets/my_select.png"
  }]
}
复制代码
  • 其他常用配置
属性类型必填/默认值描述
colorHexColor必填tab 上的文字默认颜色,仅支持十六进制颜色
selectedColorHexColor必填tab 上的文字选中时的颜色,仅支持十六进制颜色
backgroundColorHexColor必填tab 的背景色,仅支持十六进制颜色
borderStylestringblacktabbar 上边框的颜色, 仅支持 black
positionstringbottomtabBar 的位置,仅支持 bottom
custombooleanfalse自定义 tabBar

page/xxx.json

  • 这里仅列出常用配置,更多可看文档,或者啥时候我有空再写~
属性类型默认值描述
navigationBarBackgroundColorHexColor#000000导航栏背景颜色
navigationBarTextStylestringwhite导航栏标题颜色, black
navigationBarTitleTextstring导航栏标题文字内容
backgroundColorHexColor#ffffff窗口的背景色
backgroundTextStylestringdark下拉 loading 的样式, dark
enablePullDownRefreshbooleanfalse是否开启当前页面下拉刷新
onReachBottomDistancenumber50页面上拉触底事件触发时距页面底部距离,单位为px
disableScrollbooleanfalse设置为 true 则页面整体不能上下滚动
只在页面配置中有效,无法在 app.json 中设置
usingComponentsObject使用组件

生命周期钩子

小程序的生命周期

  • 必须在 app.js 中调用
属性描述
onLaunch监听小程序初始化
onShow监听小程序启动或切前台
onHide监听小程序切后台
onError错误监听函数
onPageNotFound页面不存在监听函数
onUnhandledRejection未处理的 Promise 拒绝事件监听函数
onThemeChange监听系统主题变化

页面生命周期

属性描述
onLoad监听页面加载
onShow监听页面显示
onReady监听页面初次渲染完成
onHide监听页面隐藏
onUnload监听页面卸载
onPullDownRefresh监听用户下拉动作
onReachBottom页面上拉触底事件的处理函数
onShareAppMessage用户点击右上角转发
onShareTimeline用户点击右上角转发到朋友圈
onAddToFavorites用户点击右上角收藏
onPageScroll页面滚动触发事件的处理函数
onResize页面尺寸改变时触发
onTabItemTap当前是 tab 页时,点击 tab 时触发

组件

  • 所有小程序内提供的所谓标签,我们都可以把它视为组件,他跟 html 的标签有很多相似之处,但实际微信也给我们提供了很多拓展,下面我们大概看一下常用的组件吧~

text

  • <span>
  • 有一点需要注意,小程序内可选区文本仅在 text 可用
属性类型默认值描述
user-selectbooleanfalse文本是否可选,该属性会使文本节点显示为 inline-block
spacestring显示连续空格,ensp emsp nbsp
decodebooleanfalse是否解码&nbsp; &lt; &gt; &amp; &apos; &ensp; &emsp;

view

  • <div>
属性类型默认值描述
hover-classstringnone指定按下去的样式类。当 hover-class="none" 时,没有点击态效果
hover-stop-propagationbooleanfalse指定是否阻止本节点的祖先节点出现点击态
hover-start-timenumber50按住后多久出现点击态,单位毫秒
hover-stay-timenumber400手指松开后点击态保留时间,单位毫秒
  • 以上其实一般可以使用 :active 代替,如无特殊要求,不用记

image

  • <img> + background
  • 默认宽度320px,高度240px
属性类型默认值描述
srcstring图片资源地址
modestringscaleToFill图片裁剪、缩放的模式
webpbooleanfalse默认不解析 webP 格式,只支持网络资源
lazy-loadbooleanfalse图片懒加载,在即将进入一定范围(上下三屏)时才开始加载
show-menu-by-longpressbooleanfalse开启长按图片显示识别小程序码菜单
binderroreventhandle当错误发生时触发,event.detail = {errMsg}
bindloadeventhandle当图片载入完毕时触发,event.detail = {height, width}
  • mode 对比 css
css | 说明
scaleToFillbackground-size: 100% 100%;
aspectFitbackground-size: contain;
aspectFillbackground-size: cover;
widthFixheight:auto; 此时 height 将失效
heightFixwidth:auto; 此时 width 将失效
  • 其余的 top bottom center left right 等,我个人觉得实际作用不大,都是以原图片宽高裁剪显示,真要这么做,确实用 <view> + background 比较好

navigator

  • <router-link>
属性类型默认值描述
targetstringself在哪个目标上发生跳转,默认当前小程序 self
urlstring当前小程序内的跳转链接
open-typestringnavigate跳转方式
deltanumber1当 open-type 为 'navigateBack' 时有效,表示回退的层数
hover 相关view 属性一样
  • open-type 的值
描述
navigate保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。
redirect关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
switchTab跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
reLaunch关闭所有页面,打开到应用内的某个页面
navigateBack关闭当前页面,返回上一页面或多级页面。
exit退出小程序,target="miniProgram"时生效
  • 跳转至其他小程序,当target="miniProgram"时有效
属性类型描述
app-idstring要打开的小程序 appId
pathstring打开的页面路径,如果为空则打开首页
extra-dataobject需要传递给目标小程序的数据,目标小程序可在 App.onLaunch()App.onShow() 中获取到这份数据
versionstring要打开的小程序版本
bindsuccesseventhandle跳转小程序成功
bindfaileventhandle跳转小程序失败
bindcompleteeventhandle跳转小程序完成

rich-text

  • 富文本

  • v-htmldangerouslySetInnerHTML

  • 属性

    • space:与 textspace 形同
    • nodes:节点列表/HTML String - 可为 string | array
      • string:html 字符串
      • array:类似 vnode 的形式书写 - 标签名 name; 属性 attrs; 子节点列表children;
Page({
  data: {
    nodes: [{
      name: 'div',
      attrs: {
        class: 'div_class',
        style: 'line-height: 60px; color: red;'
      },
      children: [{
        type: 'text',
        text: 'hello world'
      }]
    }]
  }
})
复制代码

button

属性类型默认值描述
sizestringdefault按钮的大小,default
typestringdefault按钮的样式类型,primary绿
plainbooleanfalse按钮是否镂空,背景色透明
disabledbooleanfalse是否禁用
loadingbooleanfalse名称前是否带 loading 图标
form-typestring用于 form 组件,点击分别会触发 form 组件的 submit
open-typestring微信开放能力
langstringen指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
hover 相关view 属性一样
  • open-type 相关
  • contact - 打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息

    • open-type="contact" 时有效的 button 属性
    属性类型默认值描述
    session-fromstring会话来源
    send-message-titlestring当前标题会话内消息卡片标题
    send-message-pathstring当前分享路径会话内消息卡片点击跳转小程序路径
    send-message-imgstring截图会话内消息卡片图片
    show-message-cardbooleanfalse是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息
    bindcontacteventhandle客服消息回调
  • share - 触发用户转发

  • getPhoneNumber - 获取用户手机号,可以从 bindgetphonenumber 回调中获取到用户信息

    • open-type="getPhoneNumber" 时有效的 button 属性
    属性类型描述
    bindgetphonenumbereventhandle获取用户手机号回调
  • getUserInfo - 获取用户信息,可以从 bindgetuserinfo 回调中获取到用户信息

    • open-type="getUserInfo" 时有效的 button 属性
    属性类型描述
    bindgetuserinfoeventhandle用户点击该按钮时,会返回获取到的用户信息,回调的detail数据与wx.getUserInfo 返回的一致
  • launchApp - 打开APP,可以通过 app-parameter 属性设定向APP传的参数

    • open-type="launchApp" 时有效的 button 属性
    属性类型描述
    app-parameterstring打开 APP 时,向 APP 传递的参数
    binderroreventhandle当使用开放能力时,发生错误的回调
    bindlaunchappeventhandle打开 APP 成功的回调
  • openSetting - 打开授权设置页

    • open-type="openSetting" 时有效的 button 属性
    属性类型描述
    bindopensettingeventhandle在打开授权设置页后回调
  • feedback - 打开“意见反馈”页面,用户可提交反馈内容并上传日志,开发者可以登录小程序管理后台后进入左侧菜单“客服反馈”页面获取到反馈内容

模板语法

  • 模板语法部分,大多与 Vue 的使用相同,我将会在下面简单说一下

数据绑定

  • 大胡子语法
Page({
    data: {
        msg: 'hello mina',
        className: 'className'
    }
})
复制代码
<!-- 标签中属性使用有区别 -->
<view class="{{className}}">{{msg}}</view>
复制代码

循环

  • 循环与 Vue 不同,并非是直接由类似 js 语法的方式表达,而是把 item index 都拆出来了,像下面的例子一样,如果我们本身使用的值就是 itemindex 可省略
<!-- *this表示数组循环项 -->
<view wx:for="{{list}}" wx:for-item="item" wx:for-index="index" wx:key="*this">{{item}}</view>
复制代码

其他

  • 简单来说呢。一般指令由 v- 变成了 wx:
  • 事件由 @ | v-on 变成了 bind | catch
  • bind 会冒泡,catch 阻止冒泡,不是所有事件都有 catch
语句/标签Vue小程序
不会真实渲染出来的标签<template><block>
ifv-ifwx:if
else ifv-else-ifwx:elif
elsev-elsewx:else
display: block;,两者相反v-showhidden
点击事件@clickbindtap

数据赋值 & 事件使用

  • 这里需要注意一下,数据的赋值、方法的传值都是不一样的
  • 简单来说,数据采用的是 react 的状态机模式,方法的传值使用的是 标签属性 的方式,希望可以通过下面的例子了解
<input type="number" value="{{num}}" bindinput="handleInput"/>
<button bindtap="handleTap" data-operation="1">+1</button>
<button bindtap="handleTap" data-operation="-1">-1</button>
<view>{{num}}</view>

<!-- model:实现双绑,不过有遗憾的是,他并不支持 obj 类型 -->
<input type="number" model:value="{{num}}" bindinput="noop" />
复制代码
  • 事件直接写在对象内
Page({
  data: {
    num: 0
  },

  handleInput(e) {
    this.setData({
      num: e.detail.value
    });
  },

  handleTap(e) {
    const { operation } = e.currentTarget.dataset;
    this.setData({
      num: +this.data.num + +operation
    });
  }
})
复制代码

wxss

尺寸单位 rpx

  • 这是我最喜欢小程序的一点,一般来说我们做屏幕适配,会用上 rem % 等等,但小程序内置了一个单位,让我们做适配非常简单,甚至不需要做适配
  • 这边建议直接看文档~ 尺寸单位

样式导入

  • 小程序支持样式导入
  • 通过 @import 引入,路径只能写相对路径

使用 less

  • 原生小程序并不支持 less、sass,我们只能先编译,再使用

  • 推荐 VsCode 插件 easy less

  • 配置为:

{
    "less.compile": {
    	"outExt": ".wxss"
    }
}
复制代码

自定义组件

  • 终于到我们最关心的 Component 了,一下写这么大一段的代码维护性确实没这么高
  • 还是那个原则,低耦合,高内聚

结构

  • 结构还是那个结构,由 json wxml wxss js 4个文件组成
  • 我们可以在文件夹右键 新建Component 快速生成4个文件
  • .json
    • component:true - 代表组件
  • js
    • 最外层函数名由页面的 Page 变为了 Component
    • properties:≈ props
    • 所有自定义事件需要放在 methods

组件间通信与事件

父传子

  • props,名字变成了 properties

    properties: {
      // props 可传类型 Array String Object
      props: {
        type: Array, // 类型
        value: [], // 默认项
        optionalTypes: [String, Object], // 多类型选项
        observer(newVal, oldVal) { } // 监听器 ≈ 只属于该字段的 watch
      }
    }
    复制代码

子传父

  • $emit,名字变成了 triggerEvent

  • 标签用 bind+事件名 接收,所传值在 e.detail

  • 或者你不想记这么多,那就像 react 一样把方法也传进去,不过父组件的方法要写在 data 里面

    this.triggerEvent('change', index);
    复制代码
    <Com bindchange="handleChange"></Com>
    复制代码

this.selectComponent

插槽 slot

  • vue 基本类似
Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },
  properties: { /* ... */ },
  methods: { /* ... */ }
})
复制代码
<view class="wrapper">
  <slot name="before"></slot>
  <slot name="after"></slot>
</view>
复制代码
<!-- 引用组件的页面模板 -->
<comp>
  <view slot="before">这里是插入到组件slot name="before"中的内容</view>
  <view slot="after">这里是插入到组件slot name="after"中的内容</view>
</comp>
复制代码

数据监听器

  • watch,但他叫 observers
  • 通配符 **
Component({
  data: {
    numberA: 1,
    numberB: 2,
    obj: {
      a: '',
      b: ''
    },
    sum: 3
  },
  observers: {
    'numberA, numberB': function (numberA, numberB) {
      // 在 numberA 或者 numberB 被设置时,执行这个函数
      this.setData({
        sum: numberA + numberB
      })
    },
    // 'obj.**' ... 监听子数据字段
    // '**' ... 监听全部数据字段
  }
})
复制代码

混入

  • mixins,名字变成了 behaviors
  • 文档~
module.exports = Behavior({
  behaviors: [],
  properties: { },
  data: { },
  methods: { },
  // ...
})
复制代码

常用生命周期

生命周期vue 对应描述
createdcreated在组件实例刚刚被创建时执行
attachedbeforeMount在组件实例进入页面节点树时执行
readymounted在组件在视图层布局完成后执行
moved在组件实例被移动到节点树另一个位置时执行
detacheddestroyed在组件实例被从页面节点树移除时执行
error每当组件方法抛出错误时执行

组件所在页面的生命周期

  • pageLifetimes 字段定义。
生命周期参数描述
show组件所在的页面被展示时执行
hide组件所在的页面被隐藏时执行
resizeObject Size组件所在的页面尺寸变化时执行
Component({
  pageLifetimes: {
    show() { },
    hide() { },
    resize() { },
  }
})
复制代码

WXS

  • 在上面的 事件使用 中,我们可以看出,小程序的事件是不可以通过 methods() 这样的方式调用的,他的引用数据值也不可以是一个执行函数的返回值
  • 如果我有需求,要这么做的时候怎么办?小程序给我们提供了一个叫 wxs 的东西
  • 这个东西也跟小程序的 渲染与逻辑 双线程通信有关,这个东西走渲染层的线程,所以也称为 辅助渲染,如果有拖拽之类需要频繁改变视图的时候,用它就对咯,会跟手很多

语法参考

  • 官方说:wxs 是小程序的一套脚本语言,与 js 是不同的语言,有自己的语法
  • 实际使用上,其实与 js 并无两样
  • 它像是一个 完全不支持ES6 的 js,也就是说 es5,还是个 残血版 的 es5
  • 模块部分,采用的是 common.js 的语法,即 module.exportsrequire

wxs 标签

  • 我们只需要把 <wxs> 看成是 <script> 即可
  • 区别是,它有一个 module 属性,而 module 的值即是 模板引入变量

示例

module.exports = {
  a: 1,
  b: function (num) { return Math.sqrt(num) }
}
复制代码
<!-- 引用的wxs -->
<wxs src="./tool.wxs" module="tool"></wxs>

<!-- 直接写wxs -->
<wxs module="ye">
	module.exports = {
      ye: '✌'
    }
</wxs>

<view>{{tool.a}}</view>
<view>{{tool.b(123)}}</view>
<view>{{ye.ye}}</view>
复制代码
// js 使用 require 导入
const tool = require('./tool.wxs');
复制代码

最后

  • 以上,大概就是这些,当然这肯定是不够的,想要玩好小程序,还是建议仔细看官方的文档嗷~
  • 接下来下一个篇章~ 小程序的常用 API
文章分类
前端
文章标签