你有没有用过Vue.js的渲染函数和JSX?

前言

真的,一定会有一些小伙伴直到完整了几个项目都做完了,却从未用过渲染函数和JSX,所以一旦遇到需要复杂处理的模板元素,其中就会夹杂大量的v-ifv-elsev-else-if……以及各种三元操作符。是时候了解一下渲染函数和JSX了,即便Vue 3在几个月后就要问世,学习一下JSX绝对没有坏处,也不会过时,JSX是React一直推崇的描述模板的方法,算是业界通用的一项技术。

官网

https://cn.vuejs.org/v2/guide/render-function.html

为什么有官网介绍,还要来个教程

官网教程是基于运行时版本的Vue.js,按照全局组件的模式为例,而我们通常是使用完整版的Vue.js,且使用单文件组件,所以本文以单文件组件为例说明。

渲染函数和JSX适用场景

当你模板中存在大量条件判断时,就适用渲染函数和JSX。比如在class中、style中、文本中、属性中存在条件判断时,会将模板搞得很冗长,而且不容易阅读,这时候适用渲染函数和JSX会让代码变得很清晰。

Hello World

  1. 在components文件夹创建HelloWorld.vue,内容是:
export default {
  props: {
    msg: {
      type: String,
      default: ""
    },
    type: {
      type: String,
      default: ""
    }
  },
  render(createElement) {
    return createElement("button", {
      class: {
        btn: true,
        success: this.type === "success",
        danger: this.type === "danger"
      },
      domProps: {
        innerText: this.msg || "默认"
      },
      on: {
        click: this.handleClick
      }
    });
  },
  methods: {
    handleClick() {
      console.log(11);
    }
  }
};
<style scoped lang="scss">
.success {
  color: green;
}
.danger {
  color: red;
}
</style>
  1. 父组件按照常规的子组件调用方法调用即可:
<hello-world type="success" msg="abc">xyz</hello-world>

JS代码从略。

  1. 效果是渲染出一段DOM:<button data-v-469af010="" class="btn success">abc</button>

  2. 讲一下HelloWorld.vue。其中props和methods不解释,只说render。render负责渲染一段DOM,前提是要给它传入VDOM,而createElement就是负责构建VDOM,我们只需要关心createElement的参数就行了。这里官网都有介绍,简单说:

    第一个参数负责声明顶级元素的标签名,也就是说,标签名到底是button还是div还是h2还是span还是其他什么。

    第二个参数就是对顶级元素的所有修饰,官网都有解释,这里只列一下:

    • class
    • style
    • attrs
    • props
    • domProps
    • on
    • nativeOn
    • directives
    • scopedSlots
    • slot
    • key
    • ref
    • refInFor

    第三个参数是可选的,是一个数组,每一个数组元素也就是一个子元素,如果是文本,直接写字符串,如果是元素,就要继续写create('标签名', {修饰对象}),这样一层一层写下去。从实践说,如果层数太多,反而不如单文件的<template>标签直观,所以尽量保持2层即可。

循环创建元素

使用v-for可以在模板中循环创建元素,在createElement里当然也可以。

官方举了一个例子,但实践中一般用不到,因为实践中往往将一个数组映射成一系列元素:

官网例子:

render: function (createElement) {
  return createElement('div',
    Array.apply(null, { length: 20 }).map(function () {
      return createElement('p', 'hi')
    })
  )
}

更贴近实践的例子,dataList靠父组件传入,然后利用map返回一系列相似的子元素:

render: function (createElement) {
  return createElement('div',
    this.dataList.map(function () {
      return createElement('p', {
        // ...
      })
    })
  )
}

如何对应<template>里的v-for/v-model/v-if/v-else指令

如何对应v-for上面已经说了,就用map就可以了。

如何对应v-model略复杂,官网有专门介绍,不说了。

v-if这类条件指令,用JS的原生if...else...即可。这里不介绍用法,但是强调一点,这就是渲染函数最有优势的地方。比如,一套条件语句如下所示,想象一下,如果将这套判断逻辑实现到<template>标签里,会是多么的恐怖,多么难以理解,某个else是哪个if的else?看的眼花。而在JS中,if...else...就会直观得多。

if () {
  if () {
    if () {
    }
  } else {
  }
} else {
}

事件和插槽

很容易,阅读官网即可。

JSX

终于到JSX了,官网的介绍比较简单。JSX说白了就是将<template>里的标签直接写到JS里,这本身在JS里是行不通的,只能依靠插件来编译。比如官方的示例:

  render: function (h) {
    return (
      <AnchoredHeading level={1}>
        <span>Hello</span> world!
      </AnchoredHeading>
    )
  }

在JS里用括号包裹一段像DOM的东西,而且还不是字符串,这在JS里是绝对行不通的,因此想用JSX就必须用插件编译成正常的模板,https://github.com/vuejs/jsx有介绍。

注意几点:

  1. JSX的一个原则是从简、小片段原则,所以不要将计算过程写入JSX中,如果写入的话,又跟<template>一样了,比如你要计算class的值,你需要在return之前,先声明一个变量比如叫classVal,然后通过一系列的JS运算算出classVal的值,然后JSX里面只能写上像上文那样比较简单的内容,比如<button class={classVal}></button>

  2. JSX默认不支持v-if等v-*指令,只支持非常少的几个指令,需要再额外装插件来弥补。

  3. JSX支持三元操作符,在{}里使用即可。

总之,vue没有主打JSX,而且JSX本身也比较弱,至少在Vue 2.0里,不是良药。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,044评论 25 707
  • 遇到南墙有的人迷途知返,有的人却固步自封不知悔改,不是所有人都有义务施舍给你同情,该自己走的路还是得自己走。解铃还...
    SEVEN_24阅读 409评论 0 2
  • 从我受教育以来,我的角色一直是不温不火,态度认真,资质平庸,学业中上的学生。我从来没有质疑过我所受的教育,也没有质...
    活动策划女青年阅读 579评论 0 6
  • 如何获得新时代的幸福? 所谓新幸福,就是摆脱金钱、时间、场所等外物的束缚,让我们重新拥有自由。 1.从“厉行节约”...
    张彦张大侠阅读 174评论 0 0
  • 毕业答辩的deadline临近,大家的答辩幻灯片做的怎样了? 相信大家制作幻灯片的第一步是找到一个自己喜欢的模版,...
    曹奇_edfa阅读 878评论 0 1