vue中的render函数(通俗易懂)

Posted 夕&月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue中的render函数(通俗易懂)相关的知识,希望对你有一定的参考价值。

文章目录

一、初步认识render函数

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false

new Vue(
  el: '#app',
  render: h => h(App)
)

在使用脚手架创建vue项目的过程,我们很容易看到render这个函数,相对于其他标签,我们对于render还是比较陌生的,因此写下这篇文章你我共同理解。

二、为什么使用render函数

VUE推荐在绝大多数情况下使用template来创建我们的html。然而在一些场景中,我们真的需要javascript的完全编程的能力,这就是render函数,它比template更接近编译器。(这是官方的话)
简单来说,我们为什么要使用render函数呢?? 便是因为我们最经常使用的一个引入。

import Vue from "vue";

这一个引入你看似没有任何问题,但问题恰恰就是出在这。在不同版本的vue中,有vue.jsvue.runtime.xxx.js这两种js文件。其中(1)vue.js是完整版的vue,包含核心功能+模板解析器。(2)vue.runtime.xxx.js是运行版vue,只包含核心功能,没有模板解析器。

VUE开发者为了让我们打包的文件能尽可能小一点,在上述引入的是运行版vue。因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,这时候就需要使用render函数去接收到的createElement函数去指定具体内容,创建html模板。

三、render函数的解析

render 函数即渲染函数,它是个函数,它的参数 createElement 也是个函数。

上边的代码中 render: h => h(App) ,这是 ES6的箭头函数的写法,可以把 h 当作 createElement 的别名。所以这段代码其实相当于:

render: function (createElement) 
    return createElement(App)

这个函数的作用就是生成一个 VNode节点,render 函数得到这个 VNode 节点之后,返回给 Vue.js 的 mount 函数,渲染成真实 DOM 节点,并挂载到根节点上。

createElement 函数的返回值是 VNode(即:虚拟节点)
有关对 VNode的介绍可以看这篇博客:VNode简介

createElement 函数的3个参数

  • 一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。类型:String | Object | Function。必需。
  • 一个包含模板相关属性的数据对象,你可以在 template 中使用这些特性。类型:Object。可选。
  • 子虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。类型:String | Array。可选。
new Vue(
  el: '#app',
  render:function (createElement) 
    //1.普通用法
    // createElement(标签,属性,[内容])
    return createElement("h2",class:"box",['hello',createElement("button",["按钮"])])
  
)


同时createElement也可以传进去一个组件,因此

render: h => h(App)

等同于

render:function (createElement) 
    return createElement(App)
  

render函数就到此结束了。

通俗易懂--快速入门Vue--2

1.Vue中的实例

<div id="exp">
    <div @click="handleClick">{{content}}</div>
</div>
</body>
<script>
    var vm = new Vue({
        // el限制一个vue实例的管理范围。
        el:"#exp",
        data:{
            content:"hello world"
        },
        methods:{
            handleClick:function () {
                alert(this.content)
            }
        }
    });
</script>
// vm为一个实例,当执行vm.$destory()就会销毁这个实例。这样通过修改数据vm.$data.message = "123",
页面不会有相应的变化

2.Vue生命周期钩子

  • 生命周期函数就是vue实例在某一个时间点自动执行的函数。
  • 注意:生命周期的函数并不会定义在methods中。

技术图片

  • 代码
<div id="app"></div>
<script>
    var vm = new Vue({
        el:"#app",
        template:`<div>{{test}}</div>`,
        data:{
            test:"hello world"
        },
        // vue实例进行基本初始化之后会被执行
        beforeCreate:function () {
            console.log("beforeCreate");
        },
        // 初始化一些外部注入,和双向绑定,当此类操作完成会调用created
        created:function () {
            console.log("created");
        },
        // 在template页面挂载之前执行函数
        beforeMount:function () {
            // 此时this.$el 还没有被渲染
            console.log("beforeMount");
        },
        // 页面渲染完执行周期函数mounted
        mounted:function () {
            // 此时this.$el 已经被渲染了,
            console.log("mounted");
        },
        // 当调用vm.$destroy(),即将被销毁时候会执行
        beforeDestroy:function () {
            console.log("beforeDestory");
        },
        // 当前实例被销毁会被调用
        destroyed:function () {
            console.log("destroyed");
        },
        // 数据发生改变,vm.test='123'还没有重新渲染数据会被执行
        beforeUpdate:function () {
            console.log("beforeUpdate");
        },
        // 重新渲染数据会被执行vm.test='123'
        updated:function () {
            console.log("updated");
        }
    })
</script>

3.模板语法

1.差值表达式

<div id="exp">
    {{name}}
</div>
或
<div>{{"my name is "+name}}</div>


<script>
    var vm = new Vue({
        // el限制一个vue实例的管理范围。
        el:"#exp",
        data:{
            name:"James"
        }
    });
</script>

2.v-text

<div v-text="name"></div>
或
<div v-text="'my name is ' + name"></div>
<script>
    var vm = new Vue({
        // el限制一个vue实例的管理范围。
        el:"#exp",
        data:{
            name:"James"
        }
    });
</script>

3.v-html

<div v-html="name_html"></div>
var vm = new Vue({
        // el限制一个vue实例的管理范围。
        el:"#exp",
        data:{
            name_html:"<h1>James</h1>"
        }
    });

4.v-on

5.v-bind

4.侦听器和计算属性

1.计算属性

  • 所谓计算属性,是通过计算得来的,下面fullName是通过定义computed内的函数得到的。
var vm = new Vue({
    el:"#exp",
    data:{
        firstName:"Dell",
        lastName:"Lee"
        age:20
    },
    computed:{
        fullName:function () {
            console.log("计算一次")
            return this.firstName + " " + this.lastName
        }
    }
});
  • 计算属性是有缓存的,上面的fullName是通过firstName和lastName拼接成的,当firstName和lastName不发生改变,比如只改变了age,是不会打印"计算一次",因为计算属性内部有缓存,为了提高性能,但是firstName或lastName发生改变,会打印"计算一次",进行重新计算一次。
  • 相比如methods方法,在age发生变化时,会再次重新调用fullName,所以计算属性更加高效:
methods:{
    fullName:function () {
    return this.firstName + " " + this.lastName
    }
},

2.侦听器

  • 通过watch监听firstName和lastName改变,如果数据发生改变会执行watch监听的函数,如果没有发生改变则不会执行。侦听器和计算属性都有缓存的概念,但是通过watch侦听器写出的代码更加复杂:
watch:{
    firstName: function () {
        this.fullName = this.firstName + " " + this.lastName
    },
    lastName: function () {
        this.fullName = this.firstName + " " + this.lastName
    },
},
  • 所以最优推荐:计算属性 > 侦听器 > methods

3.计算属性的setter和getter

  • computed不仅可以写get方法,还可以写set方法,去设置值,但是我们一般都是只写get方法,注意的是set方法需要传入一个值。
computed:{
    fullName:{
        // 当取 fullName 会执行此方法
        get:function () {
        return this.firstName + " " + this.lastName
        },
        // 当设置fullName 会执行此方法
        set:function (value) {
        var arr = value.split(" ");
        this.firstName = arr[0];
        this.lastName = arr[1];

        console.log(value)
        }
    }
}

5.vue中的样式绑定

  • 在我们写页面过程中,会给DOM添加一些样式,那么Vue中如何添加样式

方式1:class对象绑定

<style>
    .activated {
        color:red;
    }
</style>
<div id="exp">
    <div @click="handleDivClick" :class="{activated:isActivated}">{{text}}</div>
</div>

<script>
    var vm = new Vue({
        // el限制一个vue实例的管理范围。
        el:"#exp",
        data:{
            text:"hello world",
            isActivated:false
        },
        methods:{
            handleDivClick:function () {
                this.isActivated = ! this.isActivated
            }
        }
    });

方式2:数组方式

<div id="exp2">
    <div @click="handleDivClick" :class="[activated,]">{{text}}</div>
</div>


var vm2 = new Vue({
    // el限制一个vue实例的管理范围。
    el:"#exp2",
    data:{
        text:"hello world",
        activated:""
    },
    methods:{
        handleDivClick:function () {
            this.activated = this.activated === "activated" ? "" : "activated"
        }
    }
});

方式3:style改变样式 对象绑定

<div id="exp3">
    <div @click="handleDivClick" :style="styleObj">{{text}}</div>
</div>

<script>
    var vm3 = new Vue({
        // el限制一个vue实例的管理范围。
        el:"#exp3",
        data:{
            text:"hello world",
            styleObj:{
                color:"black"
            }
        },
        methods:{
            handleDivClick:function () {
                this.styleObj.color = this.styleObj.color === "black" ? "red" : "black";
            }
        }
    });

</script>

方式4:style改变样式 数组绑定

<div @click="handleDivClick" :style="[styleObj,{fontSize:'40px'}]">{{text}}</div>

6.Vue条件渲染

1.v-if

<div v-if="show">{{message}}</div>

2.v-show

<div v-show="show">{{message}}</div>
  • 它们之间区别在于,v-show其实已经在页面渲染出来了,只不过加上了display:none,而v-if还没有在页面渲染出来。
var vm = new Vue({
    // el限制一个vue实例的管理范围。
    el:"#exp",
    data:{
        show:false,
        message:"hello world"
    }
});
  • 当在终端输入:vm.show = true,它们都会显示。当经常显示去除标签时,显然v-show 更加高效。因为不会想v-if一样,不断的创建和销毁。反之v-if更合适。

3.v-if-else / v-else

  • v-else
<div id="exp">
    <div v-if="show">{{message}}</div>
    <div v-else>Bye world</div>
</div>
  • v-else-if
<div id="exp">
    <div v-if="show === 'message'">{{message}}</div>
    <div v-else-if="show ==='count'">1</div>
    <div v-else>Bye world</div>
</div>
  • v-if,v-else,v-else-if绑定标签一定要连起来写,才不能失效

4.key值的使用

  • key值的使用是必要的
<div id="app">
    <div v-if="show">
        用户名: <input type="text" key="username">
    </div>
    <div v-else>
        邮箱名: <input type="text" key="email">
    </div>
</div>
<script>
    //每个元素标签设置一个key值, 表示它是唯一标签,如果2个key不一样则不会服用原来元素标签
    // 虚拟dom算法用的内容
    var app = new Vue({
        el:"#app",
        data:{
            show:false
        }
    })
</script>

7.Vue中的列表渲染 v-for

  • 基础的使用
<div id="exp">
    <div v-for="(item,index) of list">
        {{item}}------{{index}}
    </div>
</div>
var vm = new Vue({
    // el限制一个vue实例的管理范围。
    el:"#exp",
    data:{
        list:[
            "hello,",
            "James",
            "nice",
            "to",
            "meet",
            "you"
        ]
    }
});
  • 为了提高循环的性能会给v-for标签加上唯一的key值,那么上例就可以这么写:
<div v-for="(item,index) of list" :key="index">
  • 但是往往项目中后端返回的数据都是如下类似类型的:
list:[
    {id:001102,text:"hello"},
    {id:029303,text:"James"},
    ......
]
  • 那么可以在v-for绑定唯一的key值
<div v-for="(item,index) of list" :key="item.id">
  • 当我们操作数组时,不能通过下标方式添加数组如:list[i]={id:03957569,text="bye"},只能通过vue中提供方式如下:

    • 方式1:
    push
    pop
    shift
    unshift 
    splice
    sort
    reverse
    • 方式2:
    改变数组的引用

template占位符

  • 模板占位符,通过模板占位符可以帮助我们包裹一些元素,但是在循环过程中,并不会真正被渲染到页面上。

  • 数组的循环

<template v-for="(item,index) of list" 
:key="item.id">
    <div>
        {{item.text}}
    </div>
    <span>
        {{index}}
    </span>
</template>
  • 对象的循环
<div id="app">
    <div v-for="(item,key,index) of userInfo">
        {{item}}---{{key}}---{{index}}
    </div>
</div>

<script>
    var app = new Vue({
        el:"#app",
        data:{
            userInfo:{
                name:"James",
                age:28,
                gender:"male",
                salary:"secret"
            }
        }
    });
</script>

8.补充:Vue当中set方法

  • 对象增加数据
//app为一个实例
app.$set(app.userInfo,"address","beijing")
  • 数组增加数据
vm.$set(vm.list,2,"wawawawaw")

小总结:

  • 改变数组中数据方式

    改变数组的引用
    使用数组的变异方法
    set方法
  • 改变对象中数据方式

    改变对象的引用
    set方法

以上是关于vue中的render函数(通俗易懂)的主要内容,如果未能解决你的问题,请参考以下文章

vue3生命周期及生命周期函数(钩子函数)详解通俗易懂

Vue.js 2.0 Render 函数

Vue.js(12)- 霸道的render函数渲染组件

vue v-html调用函数,说说如何利用 Render 函数来实现 Vue.js 的内置指令

vue.js中ref和$refs的使用及示例讲解

Vue.js父子组件如何传值