刚才翻了一下博客,才发现,距离自己写的第一篇Vue的博客vue.js之绑定class和style(2016-10-30)已经过去一年零两天。这一年里,自己从船厂的普通技术员,成为了一个微型不靠谱创业公司的普通码农。发过一次烧,搬了两次家,没攒下什么钱。好,牢骚发到这里,接下来谈谈传说中接近Vue底层的api==render函数。

一枚硬币的两面

很久很久以前,前端的数据和视图居住在一起,在强大的jQuery的管理下,他们相处的还算可以。但是随着页面越来越复杂,DOM树的节点越来越多,数据夹杂在DOM中变得越来越难于管理。于是一声炮响,迎来了数据驱动视图的MVVM框架,数据和视图被一条天河划分开来,整个页面的数据状态开始变得整洁起来。而连接数据视图的鹊桥是虚拟DOM,关于虚拟DOM参看全面理解虚拟DOM,实现虚拟DOM。构成DOM的每一个节点在Vue中被称为vnode。(这段不严谨,大胆假设没求证)

在我们生成真实的DOM结构时,可以写一个HTML文件描述文档结构交给浏览器去解析,同时也可以通过DOM 的api innerHTML告诉浏览器结构是什么,还可以用createElement来构建DOM树,以喜闻乐见的hello world为例,html和innerHTML api 对DOM结构的描述都是<h1>hello world</h1>,但是用createElement就变成了这个样子:

var h1 = document.createElement('h1');
var hw = document.createTextNode('hello world')
h1.appendChild(hw);
document.body.appendChild(h1);

这就是描述一个DOM结构的方式,你可以用一个html文件,一个字符串,或者一段js代码,但是他们都是在做同一件事,就是告诉浏览器该怎么渲染你想要的页面。现在我们回头看vue,在构建vue实例时,我们要写一个叫template的属性,里面是一个html一样的字符串。那么,vue对这个字符串做什么了?肯定不是羞羞的事情。事实上,vue拿它构建了虚拟DOM。

Vue.compile这个静态方法给我们展示了一个漂亮的字符串模板是怎么变成一个奇怪的render函数的:

Vue.compile('<h1>hello world</h1>')

//返回
{staticRenderFns: Array(0), render: ƒ}

render属性对应的是一个函数,在Vue的实例的上下文中调用它会得到字符串对应的虚拟DOM节点,可以把下面的代码粘贴到Vue官网的控制台下面看看效果:

let r = Vue.compile('<h1>hello world</h1>');//得到{staticRenderFns: Array(0), render: ƒ}
r.render.call(new Vue({})) //返回 VNode {tag: "h1", data: undefined, children: Array(1), text: undefined...}

于是我们抽丝剥茧,终于看到了VNode长什么样子,有tag属性,还有children,text...总之咋一看,还真的跟真实的DOM对象有几分相似,真实DOM中有tagName,children,textContent...

render函数

上面我们看到了render函数和模板字符串不同寻常的关系以及通过Vue.compile进行转换,下面来看看render函数的具体构造。要注意的是,编译后得到的不是VNode树,而是生成VNode的函数。

在创建Vue实例的过程中,如果传入的选项中有template和render两个属性,render会有更高的优先级:

new Vue({
template:'...',
render:f(){}//优先级高
})

这就表示,Vue在看到你要用render函数描述虚拟DOM时。会很高兴,因为它不用自己编译你给他的模板字符串来得到render函数,省力又省心。同时它会丢给你一个函数,这个函数是你构建虚拟DOM所需要的工具,官网上给他起了个名字叫createElement。还有约定的简写叫h,vm中有一个方法_c,也是这个函数的别名。

下面我们先来说说这个构建虚拟Dom的工具,createElement函数。参考官网createElement-参数,首先思考一个普通的html元素会传递给我们哪些信息,<h1 class='foo'>hello world</h1>,没错,我们可以得到3部分有效信息:

  1. 这个元素的标签名--h1
  2. 这个元素有什么属性/事件,class,style,onclick,name,id...
  3. 这个元素有什么子元素,这里是一个文本节点 'hello world'

上面提到,render函数和模板字符串是描述虚拟DOM树的两种方式,那么用createElement函数来描述就变成了下面这样:

craeteElement('h1', {class,style,on,attrs:{name,id}, 'hello world'})
//这里,第三个参数还有玄机,接收的参数十分灵活,详情参考官网关于这三个参数的描述

看到了吧,之前我们从字符串中得到的有效信息到了函数这边变成了输入的参数,而输出这是一个虚拟DOM节点。我们不妨叫他们createElement三剑客。

大剑客

参数类型是一个字符串或者一个对象一个函数。像下面这样:

'div'//字符串
{
data:{},
methods:{},
mounted:{}
}//一个组件选项对象
function(){return 'div'}//返回上面两种

二剑客

一个数据对象,包括对根元素html属性的描述,和组件属性的描述,详情见官网,比方说你要描述这么一个节点:

<man class="color" height="1.4m" weight="50kg" v-on:move="handle" />

需要传入的第二个参数应该是

{
'class':{color:true},
props:{height:'1.4m', weight:'50kg'},
on:{move:function handle(){}}
}

三剑客

三剑客可以是一个字符串或者一个数组,数组就表示这个根元素不止有一个虚拟子节点了。还是举个例子:

<h1> <span style="color:red">hello</span> <span>world</span> </h1>

要给createElement传入的第三个参数(第二个参数,由于根元素没什么属性,可以省略)应该是:

vm = new Vue({
render:createElement => createElement('h1',[
createElement('span',{style:{color:'red'}},'hello'),
createElement('span','world')
])
});
vm.$mount('#logo');//$mount的意思是**附体**

可以把代码复制到vue官网的控制台看效果。有句话说的好,给我一个女人,我能创造一个民族,用到这里是,给我一个createElement函数,我们创造出一课虚拟DOM树。其实render函数和slot还可以擦出不一样的火花,就到下篇介绍了(心虚)。本篇完。

Vue.js之render函数基础的更多相关文章

  1. Vue中的render函数随笔

    使用vue-cli创建项目后,再main.js里面有这样一段代码: new Vue({ render:h => h(App) }).$mount('#app') render函数是渲染一个视图, ...

  2. Vue.js学习笔记--1.基础HTML和JS属性的使用

    整理自官网教程 -- https://cn.vuejs.org/ 1. 在HTML文件底部引入Vue <script src="https://cdn.jsdelivr.net/npm ...

  3. vue中的render函数介绍

    简介:对于不了解slot的用法(参考:大白话vue-slot的用法)又刚接触render函数的同学来说,官网的解释无疑一脸懵逼,这里就整理下个人对render函数的理解 问题: 1.render函数是 ...

  4. Vue.js 相关知识(基础)

    1. Vue.js 介绍 Vue,读音 /vjuː/,类似于 view),是一套用于构建用户界面的渐进式框架(重点在于视图层). 作者:尤雨溪 注:学习 vue.js 时,一定要抛弃 jQuery 的 ...

  5. angular.js和vue.js中实现函数去抖(debounce)

    问题描述 搜索输入框中,只当用户停止输入后,才进行后续的操作,比如发起Http请求等. 学过电子电路的同学应该知道按键防抖.原理是一样的:就是说当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用 ...

  6. 在vue中结合render函数渲染指定的组件到容器中

    1.demo 项目结构: index.html <!DOCTYPE html> <html> <head> <title>标题</title> ...

  7. Vue.js学习笔记--2.基础v-指令

    整理自官网教程 -- https://cn.vuejs.org/ 1. v-bind绑定Class与Style a. 绑定Class 语法:v-bind:class="{classname: ...

  8. Vue.js货币格式化函数

    函数: const digitsRE = /(\d{3})(?=\d)/g export function currency (value, currency, decimals) { value = ...

  9. vue.js 组件共用函数的方法之一

    如果我现在写一个组件pullMore,想要用到loadMore里面的方法(函数), 那么只需要在当前组件pullMore,script里面先引入组件import loadMore from './lo ...

随机推荐

  1. 如何查看maven plugin所包含的goal

    maven项目的构建生命周期(build lifecycle)由很多阶段组成:从validate到deploy. maven插件中包含goal.这些goal可以被绑定到不同的maven的构建阶段上.g ...

  2. Markdown使用简单示例

    标题示例: 标题一 #标题一 标题二 #标题二 标题三 ###标题三 标题四 ####标题四 标题五 #####标题五 标题六 ######标题六 连接示例 [![License](图片地址)](跳转 ...

  3. Ubuntu16.04安装piwik3.0.1

    1.安装PHP环境 sudo apt-get install php7.0-fpm   2.下载piwik3.0.1 https://piwik.org/download/ 下载后解压到/var/ww ...

  4. CSV导出大量数据

    $csvname = $csvname . '.csv'; header('Content-Type: application/vnd.ms-excel;charset=GB2312'); heade ...

  5. NET应用——使用RSA构建相对安全的数据交互

    最近又被[现场破解共享单车系统]刷了一脸,不得不开始后怕:如何防止类似的情况发生? 想来想去,始终觉得将程序加密是最简单的做法.但是摩拜.ofo也有加密,为什么仍然被破解?那是因为请求在传输过程中被篡 ...

  6. 第4章 同步控制 Synchronization ----事件(Event Objects)

    Win32 中最具弹性的同步机制就属 events 对象了.Event 对象是一种核心对象,它的唯一目的就是成为激发状态或未激发状态.这两种状态全由程序来控制,不会成为 Wait...() 函数的副作 ...

  7. Linux入门之常用命令(11) 系统监控 vmstat top

    vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...

  8. jvm系列(四):jvm知识点总结

    原文链接:http://www.cnblogs.com/ityouknow/p/6482464.html jvm 总体梳理 jvm体系总体分四大块: 类的加载机制 jvm内存结构 GC算法 垃圾回收 ...

  9. 在ASP.NET Core中如何支持每个租户数据存储策略的数据库

    在ASP.NET Core中如何支持每个租户数据存储策略的数据库 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: ht ...

  10. Struts 关联DTD 文件

    Struts 的xml 文件在Eclipse 中  默认是不会有提示的. 但是我们可以关联DTD 文件, 这样子就可以出现如下的struts   提示了 1. 首先得先确保自己有Struts2 的Sr ...