vue-loader中引入模板预处理器的实现


Posted in Javascript onSeptember 04, 2019

vue-loader 是一个 webpack 的 loader,可以将指定格式编写的 Vue 组件转换为 JavaScript模块

同时,vue-loader 支持使用非默认语言,通过设置语言块的lang属性,就可以使用指定的预处理器,比如最常见的sass 语法:

<style lang="sass">
 ...
</style>

这里重点讨论使用不同的js模板引擎作为预处理器,

下面示例使用了pug模板引擎

<template lang="pug">
 div
 h1 Hello world!
</template>

1. 支持哪些模板引擎

v14 或更低版本使用 consolidate 来编译 <template lang="xxx">, 所以支持的模板引擎,从consolidate的支持列表中可以找到,包括了大部分引擎,

在vue-loader/preprocessor.js 文件里面,

// loader for pre-processing templates with e.g. pug
const cons = require('consolidate')
const loaderUtils = require('loader-utils')
const { loadOptions } = require('../utils/options-cache')

module.exports = function (content) {
 const callback = this.async()
 const opt = loaderUtils.getOptions(this) || {}

 if (!cons[opt.engine]) {
 return callback(
  new Error(
  "Template engine '" +
   opt.engine +
   "' " +
   "isn't available in Consolidate.js"
  )
 )
 }

 // allow passing options to the template preprocessor via `template` option
 const vueOptions = loadOptions(opt.optionsId)
 if (vueOptions.template) {
 Object.assign(opt, vueOptions.template)
 }

 // for relative includes
 opt.filename = this.resourcePath

 cons[opt.engine].render(content, opt, (err, html) => {
 if (err) {
  return callback(err)
 }
 callback(null, html)
 })
}

可以看到,使用consolidate 进行预处理。

v15 及以上版本,允许对vue组件中的每个部分使用其他的webpack loader,可以正常使用各种模板引擎。

使用@vue/component-compiler-utils 工具编译模板,实际在component-compiler-utils中编译template时,也把consolidate作为预处理器,使用consolidate.render编译成字符串。

2. 引入pug

需安装pug-plain-loader,利用它返回一个编译好的 HTML 字符串,

在最新的vue-cli@3.x 配置中,默认已配置好pug的相关loader, 所以安装完可以直接在<template/>中使用,

/* config.module.rule('pug') */
  {
  test: /\.pug$/,
  oneOf: [
   /* config.module.rule('pug').oneOf('pug-vue') */
   {
   resourceQuery: /vue/,
   use: [
    /* config.module.rule('pug').oneOf('pug-vue').use('pug-plain-loader') */
    {
    loader: 'pug-plain-loader'
    }
   ]
   },
   /* config.module.rule('pug').oneOf('pug-template') */
   {
   use: [
    /* config.module.rule('pug').oneOf('pug-template').use('raw') */
    {
    loader: 'raw-loader'
    },
    /* config.module.rule('pug').oneOf('pug-template').use('pug-plain') */
    {
    loader: 'pug-plain-loader'
    }
   ]
   }
  ]
  },

3. 引入dotjs或其他模板引擎,

需在vue.confg.js 里面手动配置loader, 配置规则跟引入pug类似,修改相关loader即可。

还有一点比较特殊,该模板引擎对应的loader, 必须返回字符串,

比如我们使用dotjs-loader,来解析dotjs模板,就会报错,然后查看dotjs-loader,发现

return 'export default ' + doT.template(source);

最后返回导出结果, doT.template(source)执行成功后,返回一个匿名函数,

所以想要返回最终的字符串,只有传入数据,执行函数 doT.template(source)(data)。

直接使用dotjs-loader无法达到上面的要求,只有修改loader中的返回格式,具体可以参考pug-plain-loader, 逻辑比较简单,传入模板引擎相关参数,options对应webpack 配置中的options参数,最后返回编译后的字符串。

const pug = require('pug')
const loaderUtils = require('loader-utils')

module.exports = function (source) {
 const options = Object.assign({
 filename: this.resourcePath,
 doctype: 'html',
 compileDebug: this.debug || false
 }, loaderUtils.getOptions(this))

 const template = pug.compile(source, options)
 template.dependencies.forEach(this.addDependency)
 return template(options.data || {})
}

这里可以发现问题,上面代码中options.data只是在webpack配置时传入的,并不是正式的下发数据,使用预处理模板引擎,为了返回字符串,编译函数执行在loader中进行,没有办法传入数据data,参与编译。

而且模板引擎的相关语法,不能与vue 的模板语法冲突,这样会导致js模板引擎解析后,再进行vue 模板解析时报错

如果只是纯静态页面,可以直接把需要经过模板引擎编译的内容部分抽离出去,使用require引入时,webpack会自动对应loader,解析完成后,只需在当前组件中传入data,通过v-html把生成的字符串当成HTML标签解析后输出。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS BASE64编码 window.atob(), window.btoa()
Mar 09 Javascript
用jquery等比例控制图片宽高的具体实现
Jan 28 Javascript
JS实现自动切换文字的导航效果代码
Aug 27 Javascript
JavaScript中push(),join() 函数 实例详解
Sep 06 Javascript
在js中实现邮箱格式的验证方法(推荐)
Oct 24 Javascript
js正则表达式验证密码强度【推荐】
Mar 03 Javascript
详解JS异步加载的三种方式
Mar 07 Javascript
Angular2+如何去除url中的#号详解
Dec 20 Javascript
20行JS代码实现粘贴板复制功能
Feb 06 Javascript
一步步教你利用Docker设置Node.js
Nov 20 Javascript
微信小程序实现导航栏和内容上下联动功能代码
Jun 29 Javascript
Vue.js 带下拉选项的输入框(Textbox with Dropdown)组件
Apr 17 Vue.js
解决layer图标icon不加载的问题
Sep 04 #Javascript
JSX在render函数中的应用详解
Sep 04 #Javascript
关于layui的动态图标不显示的解决方法
Sep 04 #Javascript
vue本地打开build后生成的dist文件夹index.html问题
Sep 04 #Javascript
简单谈谈javascript高级特性
Sep 04 #Javascript
在layui中使用form表单监听ajax异步验证注册的实例
Sep 03 #Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
Sep 03 #Javascript
You might like
laravel 5 实现模板主题功能(续)
2015/03/02 PHP
php实现的日历程序
2015/06/18 PHP
使用纯php代码实现页面伪静态的方法
2015/07/25 PHP
PHP中file_get_contents函数抓取https地址出错的解决方法(两种方法)
2015/09/22 PHP
Yii2隐藏frontend/web和backend/web的方法
2015/12/12 PHP
php获取POST数据的三种方法实例详解
2016/12/20 PHP
yii2 url重写并隐藏index.php方法
2018/12/10 PHP
PHP数组Key强制类型转换实现原理解析
2020/09/01 PHP
javascript的onchange事件与jQuery的change()方法比较
2009/09/28 Javascript
关于javascript event flow 的一个bug详解
2013/09/17 Javascript
JS、DOM和JQuery之间的关系示例分析
2014/04/09 Javascript
js函数定时器实现定时读取系统实时连接数
2014/04/30 Javascript
jQuery实现360°全景拖动展示
2015/03/18 Javascript
简介AngularJS的HTML DOM支持情况
2015/06/17 Javascript
JavaScript实现的多个图片广告交替显示效果代码
2015/09/04 Javascript
JQuery实现简单的图片滑动切换特效
2015/11/22 Javascript
JavaScript编写点击查看大图的页面半透明遮罩层效果实例
2016/05/09 Javascript
详解Nodejs基于mongoose模块的增删改查的操作
2016/12/21 NodeJs
对 Vue-Router 进行单元测试的方法
2018/11/05 Javascript
Vue 打包体积优化方案小结
2020/05/20 Javascript
Vue项目接入Paypal实现示例详解
2020/06/04 Javascript
解决vuex数据页面刷新后初始化操作
2020/07/26 Javascript
解决Python中由于logging模块误用导致的内存泄露
2015/04/23 Python
python方向键控制上下左右代码
2018/01/20 Python
python交互界面的退出方法
2019/02/16 Python
Python OpenCV利用笔记本摄像头实现人脸检测
2020/08/20 Python
jupyter notebook 增加kernel教程
2020/04/10 Python
【HTML5】3D模型--百行代码实现旋转立体魔方实例
2016/12/16 HTML / CSS
微软中国官方商城:Microsoft Store中国
2018/10/12 全球购物
Guess荷兰官网:美国服饰品牌
2020/01/22 全球购物
个人贷款承诺书
2014/03/28 职场文书
文明寝室申报材料
2014/05/12 职场文书
医药销售自荐书
2014/05/29 职场文书
人口与计划生育责任书
2015/05/09 职场文书
长江七号观后感
2015/06/11 职场文书
2016年综治宣传月活动宣传标语口号
2016/03/16 职场文书