在 uni-app 项目中,很多时候我们都需要一些全局统一样式的交互效果,比如 loading 及各种弹窗交互提示等。当然,大部分的项目我们都会使用 uni 自带 API 如:

uni.showLoading({title: '加载中',mask: true
});

这些 API 我们稍加封装就可以用的很 happy 了,如:

this.$loading('加载中', true)

但是实际上,有时候这个 loading 效果并不是我们想要的。除了 loading ,还有 toast 、model 。这些自带的交互效果编译到各端后的效果并不一样,显然这并不是我们想要的。而且即使是开发某一端,比如小程序。有时候我们也需要自定义这些交互效果。

比如 UI 设计的 loading 是一张 Gif 动图。产品希望 loading 开始结束时有淡入淡出效果。而且整个 App 所有的 loading 是统一的。当然更有时候除了loading,甚至toast 、model 等交互效果都是如此。

以 loading 举例。我们通常的做法是,在 components 文件夹中定义一个组件,在需要的地方调用。比如这里叫:custom-loading,同时在里面定义了 show/hide 方法:

<template><view v-if="isShow" class="custom-loading"><image src="../../loading.gif"></image></view>
</template><script>export default {data() {return {isShow: false};},methods: {show() {this.isShow = true},hide() {this.isShow = false}}}
</script><style lang="scss" scoped>.custom-loading {top: 0;left: 0;right: 0;bottom: 0;z-index: 2;display: flex;position: fixed;align-items: center;justify-content: center;image {width: 98px;height: 98rpx;}}
</style>

使用时只需要在 template 中声明:

<custom-loading ref="custom-loading" />

在需要的时候调用:

this.$refs['custom-loading'].show()

到这里,一切都没有问题。当然,聪明的你一定知道像这种使用频率比较高的组件。最好将其定义为全局组件,就可以省略组件内的 import 。但是在使用时,还是需要在 template 中声明:

<template><!-- ... --><custom-loading ref="custom-loading" /><!-- ... -->
</template>

那如果还有 custom-toast、custom-model 等,而且需要用到这些公共组件的页面会有很多。比如... 100多个。难道要在每个页面的 template 中都写上:

<custom-loading ref="custom-loading" />
<custom-toast ref="custom-toast" />
<custom-model ref="custom-model" />

很明显,这些代码是多次重复的。如果你不想敲,可以用 plop 帮你生成带有以上代码的 tamplate。但是在我看来,这些代码实际上并不需要出现在 template 中,但是最好还能实现其相应的功能。

简单的说,就是我没有在 template 中写:

<custom-loading ref="custom-loading" />

但是却能在 methods 中调用:

this.$refs['custom-loading'].show()

它不在那里,实际上它在那里。

amazing ? 其实很简单。看标题你可能也猜到了:

custom-loading 组件实际是在 vue-template-compiler 的 compile 方法编译一个 template 前手动将 <custom-loading ref="custom-loading"/> 插入到 template 中。

好了,谜底已经揭晓,看看怎么使用吧,其实很简单。

如果你比较细心,在 vue-cli 文档中关于 webpakc 的配置中有这么一个例子:

// vue.config.js
module.exports = {chainWebpack: config => {config.module.rule('vue').use('vue-loader').loader('vue-loader').tap(options => {// 修改它的选项...return options})}
}

这里我们将 options 打印出来一睹真容:

没错,options 里面竟然有 vue-template-compiler 对象!!!

注意:这种情况只有在 uni-app 中才会发生。非 uni-app 项目的 options 没有这种情况

既然能拿到 compiler 对象。我们就可以在 vue-template-compiler 将 template 模板转换为 AST 树之前往 template 中加点料。而将 template 模板转换为 AST 树的执行者就是 compiler 对象中的 compile 方法。因此,只要重写 compile 方法。

其实这种事情,还是比较常见的。Vue 2.X 对数组类型的数据结构的监听就是用重新数组原型方法实现的。

有了思路,实现起来就很快了:

// vue.config.js
module.exports = {chainWebpack: config => {config.module.rule('vue').use('vue-loader').loader('vue-loader').tap(options => {const compile = options.compiler.compileoptions.compiler.compile = (template, ...args) => {if (args[0].resourcePath.match(/^pages/)) {template = template.replace(/[sS]+?<[dD]+?>/, _ => `${_}<custom-loading ref="custom-loading" />`)}return compile(template, ...args)}return options})}
}

好了。这样配置之后,所有页面的 template 中都无需写:<custom-loading ref="custom-loading"/> ,也可以通过 $ref 拿到。但是前提是要将 custom-loading 注册为全局组件或遵循 easycom 。

最后,你当然可以把调用 loading 的操作再次封装:

this.$refs['custom-loading'].show() // => this._$loading()

好了,这就是 vue-template-compiler 在 uniapp 中我个人的一次使用。个人觉得还是非常方便。当然关于 vue-loader 和 vue-template-compiler 的使用网上已经有很多文章了,这里就不展开了。最后,这里有一个我个人用 uniapp 写的小程序,里面已经用到了这种方式。源码在:https://github.com/yinchengnuo/templateWxappUniapp 欢迎 start

vue 非template模式_vue-template-compiler 还能这么用相关推荐

  1. Java 设计模式 --- Template 模式 Java Template 模式 Java 模板设计模式

    Java 设计模式 --- Template 模式 Java Template 模式 Java 模板设计模式 一.概述 模板设计模式: 父类定义通用抽象的功能方法,子类负责具体的实现. 本文将以一个通 ...

  2. vue template 复用_Vue之组件、路由

    组件: 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树.(通俗点讲,如果你在页面上需要显示4个物品 ...

  3. C++设计模式 之 “组件协作”模式:Template Method、Strategy、Observer

    "组件协作"模式: #现代软件专业分工之后的第一个结果是"框架与应用程序的划分","组件协作"模式通过晚期绑定,来实现框架与应用程序之间的松 ...

  4. 『设计模式』瑞幸咖啡还是星巴克,一杯下午茶让我明白 设计模式--模板方法模式(Template Method Pattern)

    23种设计模式+额外常用设计模式汇总 (持续更新) 简介 Define the skeleton of an algorithm in an operation,deferring some step ...

  5. java 模板模式_Java模板模式(Template模式)

    Java模板模式(Template模式) 下一节> Template模式定义:定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中. 其实Java的抽象类本来就是Template模式,因此使 ...

  6. 设计模式学习笔记——模板(Template)模式

    设计模式学习笔记--模板(Template)模式 @(设计模式)[设计模式, 模板模式, template, 模板方法] 设计模式学习笔记模板Template模式 基本介绍 模板案例 类图 实现代码 ...

  7. 每天一个设计模式之模板方法模式(Template Method Pattern)

    所谓的模板模式就是基类(抽象类)提供出定义好的一个模板(空实现+默认实现),子类按照模板封装好的顺序去填充模板内方法的实现. 一.UML类图 图中,templateMethod是对子类暴露出的方法,它 ...

  8. Java设计模式——模板方法模式【Template Method Pattern】

    一.引言 23种设计模式大概分为三大类: 5种(创建型模式):工厂方法模式.抽象工厂模式.单例模式.原型模式.建造者模式. 7种(结构型模式):适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组 ...

  9. Callback模式和Template模式

    http://byyouside.blogbus.com/logs/5504641.html Template method被广泛的使用,像Servlet就是使用这个模式.Template motho ...

最新文章

  1. 振动力学基础与matlab应用_【日文好书推荐】振动与噪声控制技术for机械设计者...
  2. Hive的“rowid”
  3. 2011面试题大汇总
  4. iOS开发UI篇—CALayer简介
  5. 何为消息队列,为何使用消息队列,有什么消息队列插件
  6. 多线程下局部变量与全局变量的使用及区别
  7. PAT乙类1014 福尔摩斯的约会 (20 分)
  8. 对无线编码缓存的一些理解
  9. php utf-8编码 正则匹配中文
  10. mysql介质故障_pciessd异常readonly致mysql反复crash
  11. 你所知的最有价值(最有效)的思维方法是什么?
  12. 渗透测试各种扫描工具集合(好用)
  13. 14565B简单使用教程
  14. Mac取证你需要了解的那些事!
  15. 空中夺命“杀手锏”!以色列研发致命性无人机,让人毛骨悚然
  16. win10安装账户卡住_关于解决win10装系统时创建帐户时卡住了的具体解决办法
  17. spring mvc前端验证代码生成器
  18. java课设超市收银系统_基于jsp的超市收银系统-JavaEE实现超市收银系统 - java项目源码...
  19. mac下的免费UML建模工具
  20. 用金字塔原理看“⑧荣⑧耻”

热门文章

  1. 图形学实验之显示一个飞机(C++实现)
  2. 64匹马8个跑道需要多少轮才能挑选出最快的4匹马?
  3. 数据结构 - 直接插入排序法
  4. Java单例模式双重检查锁定中volatile关键字的作用
  5. 190空难_印度撤侨专机空难 官方检视黑盒子查失事原因
  6. beyond compare类似软件_Mac软件推荐 | 第 20 期
  7. ERROR 1366 (HY000): Incorrect string value......(Mysql报错解决)
  8. oracle error-1555,从另外一个角度看ORA-1555
  9. linux筛选之后备份到命令,linux find 命令使用备份
  10. java list数据的更新,java – ObservableList不更新ArrayList