微信小程序核心语法

225 阅读6分钟

数据驱动

当数据发生变化时,视图理应发生变化

在小程序中如何完成数据绑定

  1. 在 data 中定义数据
  2. 在 wxml 中通过 {{}} 使用数据

添加点击事件

小程序中可以使用**bind:tap / bindtap** (推荐使用 bindtap

修改data中的数据

想要修改 data 中的数据,那么我们需要借助一个函数 setData

setData 接收一个 对象作为参数,这个对象就是最新的 data 数据。

其中 key 为要修改的数据, value 为最新的值

访问data中的数据

可以通过 this.data 的形式访问

 /**
  * 定义事件处理的方法
  */
 onAddNum () {
  this.setData({
    'product.num': this.data.product.num + 1
  })

事件传参

在小程序中,如果想要给 **点击事件传递参数的话,**那么需要借助 event 对象 和 data- 属性 !

参数的传递包含两个部分:

  1. 形参
  2. 实参

形参:

首先先来看 形参,对于 点击事件的回调方法 而言,默认会接收一个参数 event (事件对象) 。这个 event 对象为:回调方法的唯一参数

实参:

对于 小程序 中,我们不能直接为 回调方法传递实参

而是需要通过:属性绑定的形式,把需要传递的参数绑定到 当前 DOM 元素中,绑定数据的属性需要以 data- 开头。该属性可以通过 e.target.dataset 进行访问。

// html
<button type="primary" bind:tap="onAddNum" data-step="5">num + 1</button>

// js
 onAddNum (e) {
  //  获取 data-step 的值
  let step = parseInt(e.target.dataset.step);
  this.setData({
    'product.num': this.data.product.num + step
  })
 }

双向数据绑定

  1. 什么叫做双向数据绑定?

    1. 当视图发生变化时,数据跟随发生变化。
    2. 当数据发生变化时,视图跟随发生变化.
  2. 小程序中如何实现双向数据绑定?

    1. 通过 value 为 input 视图绑定数据
    2. 通过监听 bindinput 获取视图的变化,在回调方法中修改数据
// html
<view>
    商品的数量:
    <!-- 1. 创建一个【数字输入框】 -->
    <!-- 2. 设置 【商品数量】 为输入框的初始值 -->
    <input class="num-input" type="number" value="{{ product.num }}" bindinput="onInput" />
</view>
  
// js
/**
  * 3. 监听 input 的输入事件
  */
 onInput (e) {
  //  4. 获取用户输入的值
   const val = parseInt(e.detail.value);
  //  5. 赋值给【商品数量】
  this.setData({
    'product.num': val
  })


条件渲染

小程序提供了2个api都可以实现条件渲染

  1. wx:if ... wx:elif ... wx:else(判断结果为true则进行渲染,否则不渲染)
  2. hidden(结果为true隐藏,否则不隐藏)
<!-- wx:if ... wx:elif ... wx:else:判断结果为 true 则进行渲染,否则不进行渲染 -->
  <view>
    售货员小姐姐惊呼:
    <text wx:if="{{ product.price * product.num <= 100 }}">hello 帅哥</text>
    <text wx:elif="{{ product.price * product.num > 100 && product.price * product.num < 1000 }}">哇哦 有钱人哦</text>
    <text wx:else>土豪你好</text>
  </view>
  <!-- hidden:结果为 true 则隐藏,否则不隐藏 -->
  <view>
    售货员小姐姐惊呼:
    <text hidden="{{ !(product.price * product.num <= 100) }}">hello 帅哥</text>
    <text hidden="{{ !(product.price * product.num > 100 && product.price * product.num < 1000) }}">哇哦 有钱人哦</text>
    <text hidden="{{product.price * product.num < 1000}}">土豪你好</text>
  </view>

wx-if 和 hidden 的区别:

  1. wx-if 用来控制 【组件是否会被渲染】
  2. hidden 用来控制【组件是否会被隐藏】
  3. 一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。

列表渲染

小程序提供了微信:wx-for,同时也为我们提供了一个:包裹性质的容器 block 组件,当我们去循环多个元素时,可以使用 block 进行包裹,block 组件只起到包裹的其他组件的作用,本身并不会进行渲染。

// html
<!-- 
    利用 wx:for 循环渲染商品
    默认数组的当前项的下标变量名默认为 index,
    数组当前项的变量名默认为 item
   -->
  <view class="product-box">
    <block wx:for="{{ products }}" wx:key="index">
      <view class="product-item">
        <text>商品名:{{item.name}}</text>
        <text>价格:{{item.price}}</text>
      </view>
    </block>
  </view>
  
// js
data: {
   products: [
     {
       name: '苹果',
       price: 3.2
     },
     {
       name: '面包',
       price: 5.0
     },
     {
       name: '可乐',
       price: 2.5
     }
   ]
 }

数据请求

小程序使用wx.request发起数据请求,小程序中数据请求会有限制:

  1. 只能请求 HTTPS 类型的接口

  2. 必须将接口的域名添加到信任列表中 解决方案:

  3. 生产环境:将想要请求的域名协议【更改为 HTTPS】并【添加到域名信任列表】

  4. 开发环境:通过勾选

a318e2fd4e1fa58f16f35c08d718d0c.png

get请求

// html
<view>
  <button type="primary" bindtap="onGetClick">发起 get 请求</button>
</view>
// js
// index.js
// 获取应用实例
onGetClick () {
    wx.request({
        url: 'https://api.imooc-blog.lgdsunday.club/api/test/getList',
        method: 'GET',
        success: (res) => {
            console.log(res);
        }
    })
}

post请求

// html 
  <button type="primary" bindtap="onPostClick">发起 post 请求</button>
  // js
   onPostClick () {
    wx.request({
      url: 'https://api.imooc-blog.lgdsunday.club/api/test/postData',
      method: 'POST',
      data: {
        msg: '愿大家心想事成,万事如意'
      },
      success: (res) => {
        console.log(res);
      }
    })
  }

扩展:

  1. 跨域问题:  跨域问题主要针对 浏览器 而言,而小程序宿主环境为【微信小程序客户端】,所以小程序中不存在【跨域问题】
  2. ajax 请求:  ajax 依赖于 XMLHttpRequest 对象,而小程序宿主环境为【微信小程序客户端】,所以小程序中的【网络请求】不是 ajax 请求

下拉刷新和上拉加载

上拉加载

在 【小程序】中,默认已经实现了【上拉加载】的功能,可以直接通过监听 onReachBottom 函数,来监听:页面上拉触底事件。当页面滑动到底部时,会触发 onReachBottom 函数

1.对数据进行分页处理,页面进入的时候获取第一页数据

    /**
     * 页面的初始数据
     */
    data: {
        // 当前页数
        page: 1,
        // 每页的数据量
        size: 10
    },

2.对数据进行处理

    getList() {
        return new Promise((resolve, reject) => {
            wx.request({
                url: 'url',
                method: 'GET',
                // 请求当前页的数据
                data: {
                    page: this.data.page,
                    size: this.data.size
                },
                success: (res) => {
                    resolve(res.data.data)
                }
            })
        })
    }

3.上拉操作的时候,处理数据

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom: async function () {
        console.log('onReachBottom');
        // 修改 page
        this.setData({
            page: this.data.page + 1
        })
        // 获取最新数据
        const data = await this.getList()
        // 将最新的数据补充到现有数据的后面
        this.setData({
            listData: [...this.data.listData, ...data.list]
        })
    },

4.到底给用户一个提示

// html
    <!-- 底线 -->
    <view class="bottom" wx:if="{{ listData.length === total }}">-- 我也是有底线的! --</view>
// js
data: {
    // 总数据量
    total: -1
},
onReady: async function () {
    const data = await this.getList()
    this.setData({
        listData: data.list,
        // 为总数据量赋值
        total: data.total
    })
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: async function () {
    console.log('onReachBottom');
    // 如果当前数据量已经 === 总数据量,则表示数据已经加载完成了
    if (this.data.listData.length === this.data.total) {
        return;
    }
    ...
}

下拉刷新

1.在页面首先要开启下拉刷新

// 页面.json
{
  "enablePullDownRefresh": true
}

2.开启之后我们就可以去监听onPullDownRefresh函数,

3.重置页数,重置数据源,关闭下拉刷新动画

/**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh: async function () {
        console.log('onPullDownRefresh');
        // 重置页数
        this.setData({
            page: 1
        })
         // 获取最新数据
         const data = await this.getList()
         // 将最新的数据补充到现有数据的后面
         this.setData({
             listData: data.list
         })
        //  关闭下拉刷新的动作(在真机中,下拉刷新动作不会自动关闭)
        wx.stopPullDownRefresh()
    },

页面跳转

小程序的页面跳转分为2种方式:声明式导航,编程式导航

声明式导航 小程序提供**navigator** ,使用这个组件可以完成声明式导航

<!-- 跳转到 非 tabbar 页面 -->
<block wx:for="{{ listData }}" wx:key="index">
        <view class="list-item">
            <!-- 注意:url 的表达式必须为 / 开头的页面路径 -->
            <navigator url="/pages/detail/detail">{{ index }} -- {{ item.title }}</navigator>
        </view>
    </block>

----

<!-- 跳转到 tabbar 页面 -->
<!-- 注意:跳转到 tabbar 页面,必须要指定 open-type="switchTab"-->
<navigator open-type="switchTab" url="/pages/index/index">跳转到首页</navigator>

-----

<!-- 后退页面 -->
<!-- 注意:后退页面必须指定 open-type="navigateBack" -->
<navigator open-type="navigateBack">后退</navigator>

编程式导航

小程序提供了3个api,

wx.switchTab 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

<!-- 编程式导航跳转到首页 -->
<button type="primary" bindtap="onSwitchToHome">利用 switchTab 跳转到首页</button>

onSwitchToHome () {
    wx.switchTab({
        url: '/pages/index/index',
    })
}

wx.navigateTo:保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面

<!-- 编程式导航跳转到详情页面 -->
<button type="primary" bindtap="onNavigateToDetail">利用 navigateTo 进入详情页</button>

onNavigateToDetail () {
    wx.navigateTo({
        url: '/pages/detail/detail',
    })
}

wx.navigateBack:关闭当前页面,返回上一页面或多级页面

<!-- 编程式导航后退页面 -->
<button type="primary" bindtap="onNavigateBack">利用 navigateBack 后退页面</button>

onNavigateBack () {
    wx.navigateBack({
        delta: 1,
    })
}

导航传参

  1. 以 ? 分割 url 和参数
  2. 以 = 连接参数的 key 和 value
  3. 以 & 来拼接参数
// 声明式导航传递参数
<navigator url="/pages/detail/detail?index={{index}}&title={{item.title}}">{{ index }} -- {{ item.title }}</navigator>

// 编程式导航传递参数
<button type="primary" bindtap="onNavigateToDetail" data-index="{{index}}" data-title="{{item.title}}">利用 navigateTo 进入详情页</button>

onNavigateToDetail (e) {
    const { index, title } = e.target.dataset
    wx.navigateTo({
        url: `/pages/detail/detail?index=${index}&title=${title}`,
    })
}

// 在 detail 中接收数据,并展示
<view class="msg">index:{{index}} -- title:{{title}}</view>
onLoad: function (options) {
    const {index, title} = options;
    this.setData({
        index,
        title
    })
}