使用vue 这么长时间,对vue 对源码了解还是不多,作为一个不甘平庸的前端小白,决定奋起,那么今天我们就来谈谈vue 的render 函数;
打开源码,我发现render 函数返回一个VNode; 可是我们并未在模版中写render 呀,这又是一个什么样的过程呢?
当我们创建一个Vue 实例的时候,我们会把template 编译生成render 函数;render 函数返回一个VNode; vue/src/core/instance/render.js
// 返回一个VNode;方法是实例的一个私有方法,它用来把实例渲染成一个虚拟 Node。
Vue.prototype._render = function (): VNode {
const vm: Component = this
//拿到render 函数,可以是用户自己写,也可以通过编译生成;
const { render, _parentVnode } = vm.$options
if (_parentVnode) {
vm.$scopedSlots = normalizeScopedSlots(
_parentVnode.data.scopedSlots,
vm.$slots,
vm.$scopedSlots
)
}
// set parent vnode. this allows render functions to have access
// to the data on the placeholder node.
vm.$vnode = _parentVnode
// render self
let vnode
try {
// There's no need to maintain a stack becaues all render fns are called
// separately from one another. Nested component's render fns are called
// when parent component is patched.
//不需要维护堆栈,因为所有render 函数都是单独调用的。当修补父组件时,将调用嵌套组件的呈现FN
currentRenderingInstance = vm
// 第一个参数是当前上下文,_renderProxy 是在initProxy 中定义的,第二个是
//vm.renderProxy 在生产环境下就是vm,在开发环境可能是一个proxy 对象;vm.$createElement 在initRender 函数中有定义;
vnode = render.call(vm._renderProxy, vm.$createElement)
} catch (e) {
handleError(e, vm, `render`)
// return error render result,
// or previous vnode to prevent render error causing blank component
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production' && vm.$options.renderError) {
try {
vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e)
} catch (e) {
handleError(e, vm, `renderError`)
vnode = vm._vnode
}
} else {
vnode = vm._vnode
}
} finally {
currentRenderingInstance = null
}
// if the returned array contains only a single node, allow it
if (Array.isArray(vnode) && vnode.length === 1) {
vnode = vnode[0]
}
// return empty vnode in case the render function errored out
// 如果渲染函数出错,则返回一个空的VNode;
// 如果vnode 不是VNode 的一个实例;
if (!(vnode instanceof VNode)) {
// vnode 是一个array 说为vnode 是多个根节点;VNode 虚拟dom;
if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) {
// 从render 函数中返回多个根节点,应该返回单个的根节点;
warn(
'Multiple root nodes returned from render function. Render function ' +
'should return a single root node.',
vm
)
}
vnode = createEmptyVNode()
}
// set parent
vnode.parent = _parentVnode
return vnode
}
那么我们手写render,跟使用编译的有何区别?
编译生成render 函数
index.html'
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vue-analysis</title>
</head>
<body>
<div id="app">
{{message}}
</div>
<!-- built files will be auto injected -->
</body>
</html>
main.js'
import Vue from 'vue'
/* eslint-disable no-new */
new Vue({
el: '#app',
data() {
return {
message: 'hello vue'
}
}
})
手写render 函数
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vue-analysis</title>
</head>
<body>
<div id="app">
</div>
<!-- built files will be auto injected -->
</body>
</html>
main.js
import Vue from 'vue'
/* eslint-disable no-new */
new Vue({
el: '#app',
render(createElememt) {
return createElememt('div',{
attrs: {
id: "#app1"
}
}, this.message)
},
data() {
return {
message: 'hello vue'
}
}
})
总结:
// 与直接在html中写不一样,她没有从插值变换过来的过程,之前我们是在html 中定义了插值,她在不执行的时候,先把html 的空文件渲染出来,然后在new Vue 之后,执行mounted 方法再把插值从message 中替换成真实的数据,
// 我们通过render 函数,直接手写render,我们不用在页面上显示那个插值,而是通过render函数,当它执行完毕以后,会把我们的message 替换上去,这样体验会更好一些;这里我们手写了render函数,我们就没有把template 转换成render函数这一步了;
//注意,我们挂载的元素会替换掉我们的根节点,这也是我们为什么不能用body 作为挂载点的原因,会把body 替换掉;
VueJS 实际开发中会遇到的问题,主要写一些 官方手册 上没有写,但是实际开发中会遇到的问题,需要一定知识基础。
Vue.js是一套构建用户界面的渐进式的前端框架。 vueJS与后台交互数据的方法我所了解的有以下几种
Vue是一套构建用户界面的JS渐进式框架。 Vue 只关注视图层, 采用自底向上增量开发的设计。讲解js高级之响应式、过渡效果、过渡状态。
深入理解Vue.js响应式原理。Vue教程有关的视频都讲到,我习惯响应式开发,在更早的Angular1时代,我们叫它:数据绑定(Data Binding)。你只需要在Vue实例的 data() 块中定义一些数据,并绑定到HTML
在vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示它的只属于当下的模块,这是一个非常好的举措,但是为什么要慎用呢?因为scoped往往会造成我们在修改公共组件(三方库或者项目定制的组件)的样式困难,需要增加额外的工作量
vue现在使用的人越来越多了,这篇文章主要整理一些比较优秀的移动端ui框架,推荐给大家,例如:mint UI、vux、vonic、vant、cube-ui、Muse-ui、Vue-Carbon、YDUI等
webpack是开发Vue单页应用必不可少的工具,它能管理复杂的构建步骤,并且优化你的应用大小和性能, 使你的开发工作流更加简单。在这篇文章中,我将解释使用webpack提升你的Vue应用的4种方式,包括:单文件组件、优化Vue构建过程、浏览器缓存管理、代码分离
Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。
Web 中的组件其实就是页面组成的一部分,具有高内聚性,低耦合度,互冲突等特点,有利于提高开发效率,方便重复使用,简化调试步骤等。vue 中的组件是一个自定义标签形式,扩展原生的html元素,封装可重用的代码。
Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理、数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成、编译、挂着、销毁等过程进行js控制。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!