如何理解Vue的render函数的具体用法

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

如何理解Vue的render函数的具体用法

洪定伦   2020-05-16 我要评论

本文介绍了如何理解Vue的render函数的具体用法,分享给大家,具体如下:

第一个参数(必须) - {String | Object | Function}

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <elem></elem>
  </div>
  <script>
    Vue.component('elem', {
      render: function(createElement) {
        return createElement('div');//一个HTML标签字符
        /*return createElement({
          template: '<div></div>'//组件选项对象
        });*/
        /*var func = function() {
          return {template: '<div></div>'}
        };
        return createElement(func());//一个返回HTML标签字符或组件选项对象的函数*/
      }
    });
    new Vue({
      el: '#app'
    });
  </script>
</body>
</html>

第二个参数(可选) - {Object}

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <elem></elem>
  </div>
  <script>
    Vue.component('elem', {
      render: function(createElement) {
        var self = this;
        return createElement('div', {//一个包含模板相关属性的数据对象
          'class': {
            foo: true,
            bar: false
          },
          style: {
            color: 'red',
            fontSize: '14px'
          },
          attrs: {
            id: 'foo'
          },
          domProps: {
            innerHTML: 'baz'
          }
        });
      }
    });
    new Vue({
      el: '#app'
    });
  </script>
</body>
</html>

第三个参数(可选) - {String | Array}

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <elem></elem>
  </div>
  <script>
    Vue.component('elem', {
      render: function(createElement) {
        var self = this;
        // return createElement('div', '文本');//使用字符串生成文本节点
        return createElement('div', [//由createElement函数构建而成的数组
          createElement('h1', '主标'),//createElement函数返回VNode对象
          createElement('h2', '副标')
        ]);
      }
    });
    new Vue({
      el: '#app'
    });
  </script>
</body>
</html>

两种组件写法对比

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <ele></ele>
  </div>
  <script>
    /*Vue.component('ele', {
      template: '<div id="elem" :class="{show: show}" @click="handleClick">文本</div>',
      data: function() {
        return {
          show: true
        }
      },
      methods: {
        handleClick: function() {
          console.log('clicked!');
        }
      }
    });*/
    Vue.component('ele', {
      render: function(createElement) {
        return createElement('div', {
          'class': {
            show: this.show
          },
          attrs: {
            id: 'elem'
          },
          on: {
            click: this.handleClick
          }
        }, '文本');
      },
      data: function() {
        return {
          show: true
        }
      },
      methods: {
        handleClick: function() {
          console.log('clicked!');
        }
      }
    });
    new Vue({
      el: '#app'
    });
  </script>
</body>
</html>

this.$slots用法

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <blog-post>
      <h1 slot="header"><span>About Me</span></h1>
      <p>Here's some page content</p>
      <p slot="footer">Copyright 2016 Evan You</p>
      <p>If I have some content down here</p>
    </blog-post>
  </div>
  <script>
    Vue.component('blog-post', {
      render: function(createElement) {
        var header = this.$slots.header,//返回由VNode组成的数组
          body = this.$slots.default,
          footer = this.$slots.footer;
        return createElement('div', [
          createElement('header', header),
          createElement('main', body),
          createElement('footer', footer)
        ])
      }
    });
    new Vue({
      el: '#app'
    });
  </script>
</body>
</html>

使用props传递数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <ele :show="show"></ele>
    <ele :show="!show"></ele>
  </div>
  <script>
    Vue.component('ele', {
      render: function(createElement) {
        if (this.show) {
          return createElement('p', 'true');
        } else {
          return createElement('p', 'false');
        }
      },
      props: {
        show: {
          type: Boolean,
          default: false
        }
      }
    });
    new Vue({
      el: '#app',
      data: {
        show: false
      }
    });
  </script>
</body>
</html>

VNodes必须唯一

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <!-- VNode必须唯一 -->
  <div id="app">
    <ele></ele>
  </div>
  <script>
    var child = {
      render: function(createElement) {
        return createElement('p', 'text');
      }
    };
    /*Vue.component('ele', {
      render: function(createElement) {
        var childNode = createElement(child);
        return createElement('div', [
          childNode, childNode//VNodes必须唯一,渲染失败
        ]);
      }
    });*/
    Vue.component('ele', {
      render: function(createElement) {
        return createElement('div', 
          Array.apply(null, {
            length: 2
          }).map(function() {
            return createElement(child)//正确写法
          })
        );
      }
    });
    new Vue({
      el: '#app'
    })
  </script>
</body>
</html>

v-model指令

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <el-input :name="name" @input="val=>name=val"></el-input>
    <div>你的名字是{{name}}</div>
  </div>
  <script>
    Vue.component('el-input', {
      render: function(createElement) {
        var self = this;
        return createElement('input', {
          domProps: {
            value: self.name
          },
          on: {
            input: function(event) {
              self.$emit('input', event.target.value);
            }
          }
        })
      },
      props: {
        name: String
      }
    });
    new Vue({
      el: '#app',
      data: {
        name: 'hdl'
      }
    });
  </script>
</body>
</html>

作用域插槽

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <ele>
      <template scope="props">
        <span>{{props.text}}</span>
      </template>
    </ele>
  </div>
  <script>
    Vue.component('ele', {
      render: function(createElement) {
        // 相当于<div><slot :text="msg"></slot></div>
        return createElement('div', [
          this.$scopedSlots.default({
            text: this.msg
          })
        ]);
      },
      data: function() {
        return {
          msg: '来自子组件'
        }
      }
    });
    new Vue({
      el: '#app'
    });
  </script>
</body>
</html>

向子组件中传递作用域插槽

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <ele></ele>
  </div>
  <script>
    Vue.component('ele', {
      render: function(createElement) {
        return createElement('div', [
          createElement('child', {
            scopedSlots: {
              default: function(props) {
                return [
                  createElement('span', '来自父组件'),
                  createElement('span', props.text)
                ];
              }
            }
          })
        ]);
      }
    });
    Vue.component('child', {
      render: function(createElement) {
        return createElement('b', this.$scopedSlots.default({text: '我是组件'}));
      }
    });
    new Vue({
      el: '#app'
    });
  </script>
</body>
</html>

函数化组件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>render</title>
  <script src="https://cdn.bootcss.com/vue/2.3.4/vue.js"></script>
</head>
<body>
  <div id="app">
    <smart-item :data="data"></smart-item>
    <button @click="change('img')">切换为图片为组件</button>
    <button @click="change('video')">切换为视频为组件</button>
    <button @click="change('text')">切换为文本组件</button>
  </div>
  <script>
    // 图片组件选项
    var ImgItem = {
      props: ['data'],
      render: function(createElement) {
        return createElement('div', [
          createElement('p', '图片组件'),
          createElement('img', {
            attrs: {
              src: this.data.url
            }
          })
        ]);
      }
    }
    // 视频组件
    var VideoItem = {
      props: ['data'],
      render: function(createElement) {
        return createElement('div', [
          createElement('p', '视频组件'),
          createElement('video', {
            attrs: {
              src: this.data.url,
              controls: 'controls',
              autoplay: 'autoplay'
            }
          })
        ]);
      }
    };
    /*纯文本组件*/
    var TextItem = {
      props: ['data'],
      render: function(createElement) {
        return createElement('div', [
          createElement('p', '纯文本组件'),
          createElement('p', this.data.text)
        ]);
      }
    };

    Vue.component('smart-item', {
      functional: true,
      render: function(createElement, context) {
        function getComponent() {
          var data = context.props.data;
          if (data.type === 'img') return ImgItem;
          if (data.type === 'video') return VideoItem;
          return TextItem;
        }
        return createElement(
          getComponent(),
          {
            props: {
              data: context.props.data
            }
          },
          context.children
        )
      },
      props: {
        data: {
          type: Object,
          required: true
        }
      }
    });
    new Vue({
      el: '#app',
      data() {
        return {
          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('img');
      }
    });
  </script>
</body>
</html>

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们