为了账号安全,请及时绑定邮箱和手机立即绑定
慕课专栏

目录

索引目录

mpvue原理深入解析36讲

限时优惠 ¥ 38.00

原价 ¥ 49.00

09月13日后恢复原价

限时优惠
立即订阅
03 第一式:模板语法
作者:Sam 更新时间:2019-08-14 14:08:38
加紧学习,抓住中心,宁精勿杂,宁专勿多。

—— 周恩来

本小节主要围绕模板语法来展开。无论是在小程序中还是在 mpvue 框架中模板语法都是重中之重的内容,所以本小节将分为两个方面:

  1. 微信小程序的模板语法
  2. mpvue 框架的模板语法

微信小程序的模板语法

微信小程序更新视图的方式通过状态的变更,不推荐使用 DOM 操作来更新视图,状态与视图的关系如下:

图片描述
我们通过模板语法将状态(上图中的 Data)映射到视图(上图中的 View),而在视图中我们调用setData更新状态。下面我们将修改上一节创建的 my-wx-project 项目的源码,尝试小程序状态的绑定和更新。

1 状态绑定

微信小程序的状态绑定主要有两个场景,一个是内容绑定,一个是组件属性。接下来,就让我们一一来学习。

场景一:内容绑定

在微信小程序中,想要实现内容绑定一共分为两步:

  • 第一步,定义状态(在 .js 文件中完成)

我们修改 index.js,定义一个状态,微信小程序中需要将状态定义到 data 对象下:

Page({
  data: {
    message: 'Hello Wechat mini-app!'
  }
})

提示:与 Vue 不同,小程序的状态定义不能使用 function,必须定义为 Object,如果将 data 定义为 function 将返回如下报错:

Page data error
Page.data must be an object
  • 第二步,绑定状态(在 .wxml 文件中完成)

我们修改 index.wxml,使用双括号绑定状态:

<text>{{message}}</text>

这里值得注意的是,绑定状态的双括号里面的内容要与定义状态的 data 对象的属性对应,否则是无效的。

完成修改后,模拟器上会打印出 Hello Wechat mini-app! 字样的文本内容。

场景二:组件属性

了解了内容绑定之后,我们再来看看组件属性的内容。组件属性可以向组件的属性来绑定属性,听着优点绕,我们直接通过代码来看看吧。

首先我们先修改 index.js 文件如下:

Page({
  data: {
    nodes: '<a style="color: red">Rich Text</a>'
  }
})

然后再向 rich-text 组件中绑定 nodes 状态:

<rich-text nodes="{{nodes}}"></rich-text>

rich-text是微信小程序的基础组件,同学们可以访问微信小程序官网文档了解 rich-text 的详细使用方法。

运行上面的代码得到的效果如下:

图片描述
组件属性绑定方面微信小程序与 mpvue 的差异如下:

  • 微信小程序不需要指令就能绑定属性,mpvue 需要使用指令 v-bind(简写为 :)进行绑定
  • 微信小程序属性绑定需要使用双大括号,mpvue 直接填入状态名称即可

Tip:mpvue 状态绑定的方法会在本节后面详细介绍。

接下来我们将 index.wxml 改为:

<rich-text nodes="This is {{nodes}}"></rich-text>

模板语法运行定义表达式,因此我们也可以将 index.wxml 改为:

<rich-text nodes="{{'This is ' + nodes}}"></rich-text>

上面两种写法的效果完全相同,他们都会被解析成为:

<rich-text nodes="This is <a style="color: red">Rich Text</a>">
	This is Rich Text
</rich-text>

运行效果如下:

图片描述
通过上述案例,可以发现状态绑定过程中小程序会将状态值转为 String 然后注入属性。下面的案例可以更清晰地了解这一点,首先修改 index.js

Page({
  data: {
    nodes: {
      a: 1,
      b: 2
    }
  }
})

然后修改 index.wxml

<rich-text nodes="{{nodes}}"></rich-text>

解析后源码如下:

<rich-text nodes="{"a":1,"b":2}"></rich-text>

可以看到 nodes 对象变转成了 JSON 字符串,如果将 index.wxml 修改为:

<rich-text nodes="This is {{nodes}}"></rich-text>

解析后源码如下:

<rich-textnodes="This is [object Object]">
This is [object Object]
</rich-text>

可以看到 This is {{nodes}} 被作为字符串运算,所以 nodes 被解析为 [object Object]

2 状态更新

与 mpvue 的不同,小程序的状态更新需要使用 setData 方法,这和 React 非常相似。setData 是小程序页面对象 Page 提供的 API,主要用途是更新状态并通知视图层进行更新,其定义如下:

Page.prototype.setData(Object data, Function callback)

setData 需要事件触发,或者在生命周期函数中触发,修改 index.js

Page({
  data: {
    message: 'Hello Mpvue!'
  },
  changeMessage() {
    this.setData({
      message: 'Hello imooc!'
    }, () => {
      console.log('done', this.data) // 视图更新后触发
    })
  }
})

修改 index.wxml

<text>{{message}}</text>
<button bindtap="changeMessage">更换文字</button>

执行程序,我们点击界面上的 button 后,会使文字变成 Hello imooc!,然后触发回调函数,在控制台打印日志:

图片描述

mpvue 框架的模板语法

1 mpvue 状态绑定

mpvue 框架的状态绑定同样有两个场景,一个是内容绑定,一个是属性绑定。接下来,我们依旧一一来学习。

场景一:内容绑定

mpvue 的状态绑定语法与小程序类似,我们打开 my-mpvue-project 项目,修改 pages/index/index.vue

<template>
  <div>
    <div>{{message}}</div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello Mpvue!'
      }
    }
  }
</script>

场景二:属性绑定

修改 pages/index/index.vue

<template>
  <div>
    <rich-text v-bind:nodes="nodes"></rich-text>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        nodes: '<a style="color: red">Rich Text</a>'
      }
    }
  }
</script>

mpvue 框架的属性绑定与微信小程序相比,不需要使用双括号 {{}},但需要添加 v-bind 指令,上面的 DOM 也可以简写为:

<rich-text :nodes="nodes"></rich-text>

2 mpvue 状态更新

mpvue 框架的状态更新方法与 Vue 完全一致,我们只需要修改 Vue 实例上的属性值即可,这点比微信小程序更加友好,我们将小程序的案例移植到 mpvue:

<template>
  <div>
    <div>{{message}}</div>
    <button v-on:click="change">更换文字</button>
    <!--<button @click="change">更换文字</button>-->
  </div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello Mpvue!'
      }
    },
    methods: {
      change() {
        this.message = 'Hello imooc!'
        this.$nextTick(() => {
          console.log('done', this.$data) // 视图更新后触发
        })
      }
    }
  }
</script>

这里我们可以看到 mpvue 框架和小程序开发的更多差异:

  • mpvue 更新状态直接修改 this[属性值] 即可,这得益于 Vue 框架的响应式原理,第五章会为大家详细讲解;
  • mpvue 事件绑定通过 v-on 指令实现,这一点事件绑定章节会详细说明;
  • mpvue 视图更新后回调通过 this.$nextTick 方法实现,而小程序是在 setData 方法中提供回调。

3 mpvue 框架的模板语法不支持场景

结合 mpvue 官网说明,我们一起看看 mpvue 模板语法不支持的场景:

不支持 v-html(最新版本已得到支持)

这一点在最新的 mpvue 中已经得到解决,看下面的例子:

<template>
  <div>
    <div v-html="nodes"></div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        nodes: '<a style="color: red">Rich Text</a>'
      }
    }
  }
</script>

上述源码会被解析为:

<template name="9569edd6">
  <view class="_div data-v-65f59a68">
    <rich-text nodes="{{nodes}}" class="_div data-v-65f59a68"></rich-text>
  </view>
</template>

可以看到 mpvue 可以正确识别 v-html 指令并转化为 rich-text 组件。

不支持部分复杂的 JavaScript 渲染表达式

受到小程序对模板语法支持的限制,部分表达式不能够支持,如字符串方法调用,如:

<template>
  <div>
    <div>{{message.split('.')}}</div>
    <div>{{message.toString()}}</div>
    <div>{{message.toLowerCase()}}</div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello.Mpvue'
      }
    }
  }
</script>

如果发现这种场景,可以通过 computed 计算属性来解决:

<template>
  <div>
    <div>{{msg}}</div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello.Mpvue'
      }
    },
    computed: {
      msg() {
        return this.message.split('.')
      }
    }
  }
</script>

运算符都可以良好地支持,以下表达式都能够得到支持:

<template>
  <div>
    <!--四则运算--><div>{{a + b}} {{a - b}} {{a * b}} {{a / b}}</div>
    <!--三目运算符和比较运算符--><div>{{a === 1 ? true : false}} {{a < b}} {{a > b}}</div>
    <!--连续运算--><div>{{a + b - a + b * b}}</div>
    <!--位运算符--><div>{{a & b}} {{a | c}} {{a ^ b}} {{~c}} {{b << a}} {{b >> a}}</div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        a: 1,
        b: 2,
        c: 0
      }
    }
  }
</script>

不支持过滤器

过滤器是 Vue 框架非常实用的特性,下面是一个 Vue 框架过滤器的例子:

<!DOCTYPE>
<html>
  <head>
    <title>Vue Filter</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">{{message | Lower}}</div>
    <script>
      new Vue({
        el: '#app',
        data() {
          return { message: 'Hello Mpvue!' }
        },
        filters: {
          Lower(value) { return value.toLowerCase() }
        }
      })
    </script>
  </body>
</html>

借助过滤器我们可以对 message 进行二次处理。本例中,我们将 message 中所有字母改为小写,很遗憾微信小程序不支持 filters 特性:

<template>
  <div>
    <div id="app">{{message | Lower}}</div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello Mpvue!'
      }
    },
    filters: {
      Lower(value) { return value.toLowerCase() }
    }
  }
</script>

上面的例子中,小程序会将 message | Lower 中的 | 作为按位或运算进行运算。不仅如此,小程序还不能支持直接调用业务方法,我们先修改小程序项目的 index.wxml

<text>{{lower(message)}}</text>

再修改 index.js

Page({
  data: {
    message: 'Hello Mpvue!'
  },
  lower(msg) {
    return msg.toLowerCase()
  }
})

小程序编译后的源码:

<text></text>

这与小程序视图层和逻辑层架构分离有关,为了解决这个问题,小程序为我们引入了 wxs 文件,我们先创建 wxs 文件 index.wxs

function Lower(value) {
  return value.toLowerCase()
}

module.exports = {
  Lower: Lower
}

这里要注意 wxs 不支持使用对象的简写:

module.exports = {
  Lower
}

之后我们修改 index.wxml

<wxs module="utils" src="index.wxs"></wxs>

<text>{{utils.Lower(message)}}</text>
<button bindtap="changeMessage">更换文字</button>

index.js 和之前一致:

Page({
  data: {
    message: 'Hello Mpvue!'
  },
  changeMessage() {
    this.setData({
      message: 'Hello imooc!'
    }, () => {
      console.log('done', this.data) // 视图更新后触发
    })
  }
})

运行后,可以获得正确的结果,message 显示为:hello mpvue!,点击按钮后,显示的文字为:hello imooc!,说明过滤器生效。虽然小程序已有 wxs 支持过滤器特性,mpvue 目前仍不能支持,官方建议我们对数据进行预处理,当然已有人在 GitHub 提出对过滤器支持的 feature 并且已经 open,让我们保持关注吧!

总结

本节我们讲解了微信小程序和 mpvue 对状态绑定及更新的方法:

  • 微信小程序:
    • 使用 Mustache 语法进行状态绑定;
    • 使用 setData 进行状态更新;
    • 通过向 setData 方法传入回调函数,实现方法渲染后回调;
    • 模板语法中不支持复杂方法调用(如 String 的原型方法),只能支持算术运算符;
    • 过滤器需要借助 wxs 特性实现。
  • mpvue 框架:
    • 使用 Mustache 语法进行状态绑定;
    • 使用 this[属性名] 进行状态更新;
    • 使用 this.$nextTick 进行渲染后回调;
    • 支持 v-html 指令,会自动转换为 rich-text 组件;
    • 模板语法中不支持复杂的 Javascript 表达式;
    • 不支持过滤器特性,替代方案是数据预处理。

本节关键概念

概念 内容
状态 状态具有响应式的特点,状态值的变更会驱动视图更新。小程序和 mnpvue 中均定义在 data
视图 视图指用于生成用户界面的布局文件,小程序中的视图文件为wxml,而 mpvue 中为 .vue 文件的 template 模板
组件 组件指构成用户界面的特殊对象,小程序提供了基础组件,也可运行我们自定义组件,mpvue 继承了 Vue 组件化特性,具有完全组件化的能力,如:<rich-text></rich-text> 就是组件
属性 属性指构成对象的元素,如 <rich-text nodes="hello"></rich-text> 中的 nodes 就是组件 rich-text 的属性
模板语法 又称 Mustache 语法,将状态绑定到视图中,需要使用模板语法,小程序和 mpvue 均使用双大括号 {{}} 作为模板语法
}
限时优惠 ¥ 38.00 ¥ 49.00

你正在阅读课程试读内容,订阅后解锁课程全部内容

千学不如一看,千看不如一练

手机
阅读

扫一扫 手机阅读

mpvue原理深入解析36讲
限时优惠 ¥ 38.00 ¥ 49.00

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信