文档章节

函数式组件完整例子

tianyawhl
 tianyawhl
发布于 08/14 16:40
字数 1382
阅读 1
收藏 0

之前创建的组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法。它只是一个接收参数的函数。
在下面这个例子中,我们标记组件为 functional,这意味它是无状态 (没有响应式数据),无实例 (没有 this 上下文)。

一个 函数式组件 就像这样:

Vue.component('my-component', {
  functional: true,
  // Props 可选
  props: {
    // ...
  },
  // 为了弥补缺少的实例
  // 提供第二个参数作为上下文
  render: function (createElement, context) {
    // ...
  }
})

注意:在 2.3.0 之前的版本中,如果一个函数式组件想要接受 props,则 props 选项是必须的。在 2.3.0 或以上的版本中,你可以省略 props 选项,所有组件上的属性都会被自动解析为 props。

在 2.5.0 及以上版本中,如果你使用了单文件组件,那么基于模板的函数式组件可以这样声明:

<template functional>
</template>

组件需要的一切都是通过上下文传递,包括:

  • props:提供所有 prop 的对象
  • children: VNode 子节点的数组
  • slots: 返回所有插槽的对象的函数
  • data:传递给组件的数据对象,作为 createElement 的第二个参数传入组件
  • parent:对父组件的引用
  • listeners: (2.3.0+) 一个包含了所有在父组件上注册的事件侦听器的对象。这只是一个指向 data.on 的别名。
  • injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。

在添加 functional: true 之后,锚点标题组件的 render 函数之间简单更新增加 context参数,this.$slots.default 更新为 context.children,之后this.level 更新为 context.props.level。 

因为函数式组件只是一个函数,所以渲染开销也低很多。然而,对持久化实例的缺乏也意味着函数式组件不会出现在 Vue devtools 的组件树里。

在上面多个context的属性中,其中context.props、context.data、context.children这3个用的比较多。 context.props用来传递数据,context.data传递属性如class、id等,context.children指插槽的默认值this.$slots.default。

例一

<body>
    <div id="app">
        <my-function-button v-bind:class="className" id="btn1">button</my-function-button>
    </div>
    <script src="js/vue.js"></script>
    <script>
   
     Vue.component("my-function-button",{
        functional:true,
        render:function(createElement,context){
            return createElement("button",context.data,context.children)
        }
     })

    new Vue({
        el: '#app',
        data: {
            className:"btnname"
        },
    });
    //context.data 是用来传递属性的,传递数据是context.props
    </script>
</body>

渲染成 :<button id="btn1" class="btnname">button</button>

例二

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>AdminLTE 2 | Morris.js Charts</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- Morris charts -->

</head>

<body>
    <div id="app">
        <smart-list :items="items" v-bind:number="1" class="specialColor">hi</smart-list>
    </div>
    <script src="js/vue.js"></script>
    <script>
    // 组件1
    var EmptyList = {
        template: "<p>Empty list</p>"
    }
    // 组件2
    var Tablist ={
        props:["chuandiData"],
        template:`
           <ul>
               <li v-for="item in chuandiData">{{item.name}}</li>
           </ul>
        `
    }

    // 组件3
    var component3 = {
        template:` 
        <div> this is component3 </div>
        `
    }
    Vue.component("smart-list", {
        functional: true,
        props: {
            items: {
                type: Array,
                required: true
            }
        },
        render: function(createElement, context) {
            console.log(context)
            function appropriateListComponent() {
                var items = context.props.items
                if (items.length === 0) {
                    return EmptyList
                }
                if (items.length == 3) return Tablist
            }
            return createElement(
                appropriateListComponent(),
                {
                    props:{
                        chuandiData:context.props.items
                    }
                }
               
            )
        }
    })


    new Vue({
        el: '#app',
        data: {
            items: [{
                    name: 'a',
                    id: 0
                },
                {
                    name: 'b',
                    id: 1
                },
                {
                    name: 'c',
                    id: 2
                }
            ]

        },

    });
    //context.data 是用来传递属性的,传递数据是context.props
    </script>
</body>

</html>

渲染成:

<ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
</ul>

 

例三

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>AdminLTE 2 | Morris.js Charts</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- Morris charts -->

</head>

<body>
    <div id="app">
        <smart-list :items="items" v-bind:number="1" class="specialColor">hi</smart-list>
    </div>
    <script src="js/vue.js"></script>
    <script>
    // 组件1
    var EmptyList = {
        template: "<p>Empty list</p>"
    }
    // 组件2
    var Tablist = {
        template: `
         <ul>
             <li><slot></slot></li>
         </ul>
        `
    }
    Vue.component("smart-list", {
        functional: true,
        props: {
            items: {
                type: Array,
                required: true
            }
        },
        render: function(createElement, context) {
            console.log(context)
            function appropriateListComponent() {
                var items = context.props.items
                if (items.length === 0) {
                    return EmptyList
                }
                if (items.length == 3) return Tablist
            }
            return createElement(
                appropriateListComponent(),
                context.children
            )
        }
    })


    new Vue({
        el: '#app',
        data: {
            items: [{
                    name: 'a',
                    id: 0
                },
                {
                    name: 'b',
                    id: 1
                },
                {
                    name: 'c',
                    id: 2
                }
            ]

        },

    });
    //context.data 是用来传递属性的,传递数据是context.props
    </script>
</body>

</html>

渲染成:<ul><li>hi</li></ul>

 

例四

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>AdminLTE 2 | Morris.js Charts</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- Morris charts -->
    <link rel="stylesheet" href="../../dist/css/Basic.css">
    <link rel="stylesheet" href="../../dist/css/lanrenzhijia.css">
</head>

<body>
    <div id="app">
        <smart-item :data1="data">hi</smart-item>
        <button @click="change('img')">切换为图片为组件</button>
        <button @click="change('video')">切换为视频为组件</button>
        <button @click="change('text')">切换为文本组件</button>
    </div>
    <script src="js/vue.js"></script>
    <script>
    // 图片组件选项
    var ImgItem = {
        props: ['data2'],
        render: function(createElement) {
            return createElement('div', [
                createElement('p', '图片组件'),
                createElement('img', {
                    attrs: {
                        src: this.data2.url
                    }
                })
            ]);
        }
    }
    // 视频组件
    var VideoItem = {
        props: ['data2'],
        render: function(createElement) {
            return createElement('div', [
                createElement('p', '视频组件'),
                createElement('video', {
                    attrs: {
                        src: this.data2.url,
                        controls: 'controls',
                        autoplay: 'autoplay'
                    }
                })
            ]);
        }
    };
    /*纯文本组件*/
    var TextItem = {
        props: ['data2'],//2、接收1传过来的props对象
        render: function(createElement) {
            return createElement('div', [
                createElement('p', '纯文本组件'),
                createElement('p', this.data2.content)
            ]);
        }
    };

    Vue.component('smart-item', {
        functional: true,
        render: function(createElement, context) {
            function getComponent() {
                var data = context.props.data1;
                if (data.type === 'img') return ImgItem;
                if (data.type === 'video') return VideoItem;
                return TextItem;
            }
            return createElement(
                getComponent(), {
                    props: {
                        data2: context.props.data1 //getComponent()返回的是组件,props是用来传递数据给返回的组件,如:TextItem组件
                    }
                }
                ,context.children  //可以不需要
            )
        },
        props: {
            data1: {
                type: Object,
                required: true
            }
        }
    });
    new Vue({
        el: '#app',
        data: {
            data: {}
        },
        methods: {
            change: function(type) {
                if (type === 'img') {
                    this.data = {
                        type: 'img',
                        url: 'https://raw.githubusercontent.com/iview/iview/master/assets/logo.png'
                    }
                } else if (type === 'video') {
                    this.data = {
                        type: 'video',
                        url: 'http://vjs.zencdn.net/v/oceans.mp4'
                    }
                } else if (type === 'text') {
                    this.data = {
                        type: 'text',
                        content: '这是一段纯文本'
                    }
                }
            }
        },
        created: function() {
            this.change('text');
        }
    });
	//
    </script>
</body>

</html>

 

© 著作权归作者所有

共有 人打赏支持
tianyawhl
粉丝 1
博文 207
码字总数 103497
作品 0
常州
前端工程师
[译] React 实现条件渲染的多种方式和性能考量

原文地址:8 React conditional rendering methods 原文作者:Esteban Herrera 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:Dong Han 校对者:Jessica Shao,doc...

卷头驴先生
07/06
0
0
TypeScript 2.8下的终极React组件模式

译者简介 zqlu 蚂蚁金服·数据体验技术团队 翻译自Ultimate React Component Patterns with Typescript 2.8,作者Martin Hochel 这篇博客受React Component Patterns启发而写 在线Demo 有状态...

蚂蚁金服数据体验技术
05/25
0
0
Vue Render介绍和一些基本的实例

为啥研究这个?在之前开发组件库的过程中,遇到了许多遗留的问题,包括数据模板渲染、组件按需加载、引入自定义组件插槽等等,所以为了修复和避免这些问题,学习一波更接近编译器的编写方式,...

宗仔GEG
07/18
0
0
渲染函数-深入 data 对象

我们平时在家是很少看电视的,最近看了几期最强大脑,真的被震惊到了,为什么他们的大脑容量那么大呢?并且非常机敏。海量的信息可以在很短的时间内记住,真是最遥远的距离莫过于我还没弄明白...

tianyawhl
08/04
0
0
React - Refs 和 DOM

  在常规的 React 数据六中, 是父组件与子组件交互的唯一方法。如果需要改子元素,你需要用新的去重新渲染子元素。 然而,在少数情况下,你需要在常规数据流外强制修改子元素。被修改的子元...

果汁凉茶丶
07/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

NIO与BIO的区别、NIO的运行原理和并发使用场景

NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的...

Java干货分享
38分钟前
1
0
Makefile 学习 1 - 基于若干 Blog 的汇总

基于若干 Blog 汇总的 makefile 教程 陈皓 https://blog.csdn.net/haoel/article/details/2886 Makefile 基础知识 1. 什么是 Makefile? 规定软件工程的编译规则。一个工程中的源文件,其按类...

公孙衍
51分钟前
1
0
72.告警系统邮件引擎 运行告警系统

20.23/20.24/20.25 告警系统邮件引擎 20.26 运行告警系统 20.23/20.24/20.25 告警系统邮件引擎 邮件首先要有一个mail.py,以下。 因为我们之前zabbix的时候做过,就可以直接拷贝过来 mail.s...

王鑫linux
今天
1
0
09-利用思维导图梳理JavaSE-

09-利用思维导图梳理JavaSE-Java IO流 主要内容 1.Java IO概述 1.1.定义 1.2.输入流 - InputStream 1.3.输出流 - OutputStream 1.4.IO流的分类 1.5.字符流和字节流 2.InputStream类 2.1.File...

飞鱼说编程
今天
3
0
Spring Cloud 微服务的那点事

在详细的了解SpringCloud中所使用的各个组件之前,我们先了解下微服务框架的前世今生。 单体架构 在网站开发的前期,项目面临的流量相对较少,单一应用可以实现我们所需要的功能,从而减少开...

我是你大哥
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部