小程序入坑


小程序简介

小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验。

小程序与普通网页开发的区别

小程序的主要开发语言是 JavaScript ,小程序的开发同普通的网页开发相比有很大的相似性。对于前端开发者而言,从网页开发迁移到小程序的开发成本并不高,但是二者还是有些许区别的。
普通网页开发:
​ 渲染线程和脚本线程是互斥的。
网页开发者可以使用到各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作
网页开发者需要面对的环境是各式各样的浏览器,PC 端需要面对 IE、Chrome、QQ 浏览器等,在移动端需要面对 Safari、Chrome 以及 iOS、Android 系统中的各式 WebView
小程序:
渲染线程和脚本线程是分开的,分别运行在不同的线程中。
小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的 DOM API 和 BOM API,这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
而小程序开发过程中需要面对的是两大操作系统 iOS 和 Android 的微信客户端,以及用于辅助开发的小程序开发者工具,小程序中三大运行环境也是有所区别的,如表所示。

运行环境 逻辑层 渲染层
iOS JavaScriptCore WKWebView
安卓 V8 chromium 定制内核
小程序开发者工具 NWJS Chrome WebView

小程序与普通网页开发文件对比

结构 传统 Web 微信小程序
结构 HTML WXML
样式 CSS WXCSS
逻辑 JavaScript JavaScript
配置 JSON

基本项目目录结构

小程序配置文件

小程序应用程序会包括最基本的两种配置文件,一种是全局的 app.json 和 页面自已的 page.json

全局配置

小程序根目录下的 app.json 文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。
以下是一个包含了部分常用配置选项的 app.json :

{
  "pages": [
    "pages/index/index",
    "pages/logs/index"
  ],
  "window": {
    "navigationBarTitleText": "Demo"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页"
    }, {
      "pagePath": "pages/logs/index",
      "text": "日志"
    }]
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "debug": true
}

完整配置项说明请参考 小程序全局配置

页面配置

每一个小程序页面也可以使用同名 .json 文件来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json 的 window 中相同的配置项。

{
  "navigationBarBackgroundColor": "#ffffff",
  "navigationBarTextStyle": "black",
  "navigationBarTitleText": "微信接口功能演示",
  "backgroundColor": "#eeeeee",
  "backgroundTextStyle": "light"
}

完整配置项说明请参考 小程序页面配置

sitemap 配置

小程序根目录下的 sitemap.json 文件用于配置小程序及其页面是否被微信索引
完整配置项说明请参考 sitemap 配置

组件的使用

组件使用说明请参考 组件文档

基本语法

数据绑定

.js 文件

Page({
  data: {
    msg: "Hello !!!",
    num: 100,
    show: true,
    parson: {
      name: "鸣人",
      age: 18
    }
  },
})

.wxml 文件

<view>
  <!-- 字符串类型 -->
  <view>{{msg}}</view>
  <!-- 数字类型 -->
  <view>{{num}}</view>
  <!-- 布尔类型 -->
  <checkbox checked="{{show}}">是否展示</checkbox>
  <!-- 对象类型 -->
  <view>名字 : {{parson.name}} 年龄 : {{parson.age}}</view>
</view>

运算

<view>
  <!-- 数字加减 -->
  <view>{{1 + 1}}</view>
  <!-- 字符串拼接 -->
  <view>{{"1" + "1"}}</view>
  <!-- 三元表达式 -->
  <view>{{10 % 2 === 0 ? "偶数" : "奇数"}}</view>
</view>

列表渲染

.js 文件

Page({
  data: {
    dataList: [{
        id: 1,
        name: "鸣人"
      },
      {
        id: 2,
        name: "佐助"
      },
      {
        id: 2,
        name: "雏田"
      },
      {
        id: 2,
        name: "小樱"
      },
    ],
    parson: {
      name: "鸣人",
      age: 18
    }
  },
})

.wxml 文件

<view>
  <!-- wx:for="{{数组或者对象}}" wx:for-item="循环项的名称" wx:for-index="循环项的索引" wx:key="唯一值,用于提高列表渲染性能" -->
  <!-- 如果数组为普通数组 列如:[1,2,3,4]   wx:key="*this"  *this 表示循环项-->
  <!--
  默认情况下:
  可以不写 wx:for-item="item"  wx:for-index="index",小程序会默认添加(只有一层循环下可以省略)
  当出现 数组的嵌套循环的时候 以下绑定 不能重名
  wx:for-item="item"  wx:for-index="index"
  -->
  <view wx:for="{{dataList}}" wx:for-item="item" wx:for-index="index" wx:key="id">
    索引 :{{index}}
    值 : {{item.name}}
  </view>

  <view wx:for="{{parson}}" wx:for-item="value" wx:for-index="key" wx:key="id">
    属性:{{key}}
    值:{{value}}
  </view>
</view>

条件渲染

<!--
  场景使用:
   wx:if :当标签不是频繁切换的时候优先使用 (直接把标签从页面移除)
   hidden :当标签频繁切换的时候优先使用 (通过使用样式的方式来切换显示)
   注意 :(hidden 属性不可和样式 display 一起使用,否则 hidden 属性会失效)
-->
<view>
  <!-- wx:if="{{true/false}}" -->
  <view wx:if="{{true}}"> 显示 </view>
  <view wx:if="{{false}}"> 隐藏 </view>

  <!-- wx:if  wx:elif wx:else-->
  <view wx:if="{{false}}"> 1 </view>
  <view wx:elif="{{false}}"> 2 </view>
  <view wx:else> 3 </view>

  <!-- hidden 默认为 true-->
  <view hidden="{{false}}">hidden1</view>
  <view hidden>hidden2</view>
</view>

事件绑定

.js 文件

Page({
  data: {
    num: 0
  },

  // 输入框事件
  handInput(e) {
    this.setData({
      num: Number(e.detail.value)
    })
  },

  //加 减 事件
  handbindtap(value) {
    const num = value.currentTarget.dataset.num
    this.setData({
      num: this.data.num + num
    })
  }
})

.wxml 文件

<view>
  <input type="text" bindinput="handInput" />
  <button bindtap="handbindtap" data-num="{{1}}">+</button>
  <button bindtap="handbindtap" data-num="{{-1}}">-</button>
  <view>{{num}}</view>
</view>

自定义组件

详情使用说明请参考 自定义组件文档

创建自定义组件

类似于页面,一个自定义组件由 json wxml wxss js 4 个文件组成。要编写一个自定义组件,首先需要在 json 文件中进行自定义组件声明(将 component 字段设为 true 可将这一组文件设为自定义组件)

{
  "component": true
}

同时,还要在 wxml 文件中编写组件模板,在 wxss 文件中加入组件样式,它们的写法与页面的写法类似。具体细节和注意事项参见 组件模板和样式

<!-- 这是自定义组件的内部WXML结构 -->
<view class="inner">
  {{innerText}}
</view>
<slot></slot>
/* 这里的样式只应用于这个自定义组件 */
.inner {
  color: red;
}

在自定义组件的 js 文件中,需要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法。

Component({
  properties: {
    // 这里定义了innerText属性,属性值可以在组件使用时指定,由父级传递过来
    innerText: {
      type: String,
      value: 'default value',    //默认值
    }
  },
  data: {
    // 这里是一些组件内部数据
    someData: {}
  },
  methods: {
    // 这里是一个自定义组件自已的方法
    customMethod: function(){}
  }
})

使用自定义组件: 使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径

{
  "usingComponents": {
    "component-tag-name": "path/to/the/custom/component"
  }
}

Component 构造器

Component 构造器可用于定义组件,调用 Component 构造器时可以指定组件的属性、数据、方法等。
详细的参数含义和使用请参考 Component 参考文档

Component({

  behaviors: [],

  properties: {
    myProperty: { // 属性名
      type: String,
      value: ''
    },
    myProperty2: String // 简化的定义方式
  },
  
  data: {}, // 私有数据,可用于模板渲染

  lifetimes: {
    // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
    attached: function () { },
    moved: function () { },
    detached: function () { },
  },

  // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
  attached: function () { }, // 此处attached的声明会被lifetimes字段中的声明覆盖
  ready: function() { },

  pageLifetimes: {
    // 组件所在页面的生命周期函数
    show: function () { },
    hide: function () { },
    resize: function () { },
  },

  methods: {
    onMyButtonTap: function(){
      this.setData({
        // 更新属性和数据的方法与更新页面数据的方法类似
      })
    },
    // 内部方法建议以下划线开头
    _myPrivateMethod: function(){
      // 这里将 data.A[0].B 设为 'myPrivateData'
      this.setData({
        'A[0].B': 'myPrivateData'
      })
    },
    _propertyChange: function(newVal, oldVal) {

    }
  }

})

组件间通信与事件

组件间的基本通信方式有以下几种

  • WXML 数据绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)。具体在 组件模板和样式 章节中介绍。
  • 事件:用于子组件向父组件传递数据,可以传递任意数据。
  • 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法

父子组件传值


  目录