block by nitaku 08ea8fb868ce5bd7661f90fca1881faf

Vue.js custom render

Full Screen

A Vue.js custom render function is used to display a customizable box containing text or list sections.

index.js

// Generated by CoffeeScript 1.10.0
(function() {
  var app, list_component, sections_component, text_component;

  list_component = {
    props: {
      value: {
        type: Array,
        required: true
      }
    },
    template: '<div>\n  <ol>\n    <li v-for="item in value" :class="{emph: item.emph}">{{item.text}}</li>\n  </ol>\n</div>'
  };

  text_component = {
    props: {
      value: {
        type: String,
        required: true
      }
    },
    template: '<div>{{value}}</div>'
  };

  sections_component = {
    props: {
      value: {
        type: Array,
        required: true
      }
    },
    render: function(createElement) {
      var children;
      children = this.value.map(function(d) {
        return createElement(d.type + "-section", {
          props: {
            value: d.value
          }
        });
      });
      return createElement('div', {
        "class": 'sections'
      }, children);
    },
    components: {
      'text-section': text_component,
      'list-section': list_component
    }
  };

  app = new Vue({
    el: '#app',
    data: {
      sections1: [
        {
          type: 'text',
          value: 'This is a text section'
        }, {
          type: 'list',
          value: [
            {
              text: 'important',
              emph: true
            }, {
              text: 'not important',
              emph: false
            }, {
              text: 'important',
              emph: true
            }
          ]
        }, {
          type: 'text',
          value: 'Footer'
        }
      ],
      sections2: [
        {
          type: 'text',
          value: 'A'
        }, {
          type: 'text',
          value: 'B'
        }, {
          type: 'text',
          value: 'C'
        }, {
          type: 'list',
          value: [
            {
              text: 'one!',
              emph: true
            }, {
              text: 'two',
              emph: false
            }
          ]
        }
      ]
    },
    components: {
      'sections': sections_component
    }
  });

}).call(this);

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Vue.js custom render</title>
  <link type="text/css" href="index.css" rel="stylesheet"/>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
  
  <div id="app">
    <sections :value="sections1"/>
    <sections :value="sections2"/>
  </div>
  
  <script src="index.js"></script>
</body>
</html>

index.coffee

list_component =
  props:
    value:
      type: Array
      required: true
  template: '''
    <div>
      <ol>
        <li v-for="item in value" :class="{emph: item.emph}">{{item.text}}</li>
      </ol>
    </div>
  '''

text_component =
  props:
    value:
      type: String
      required: true
  template: '''
    <div>{{value}}</div>
  '''
  
sections_component =
  props:
    value:
      type: Array
      required: true
  render: (createElement) ->
    children = @value.map (d) ->
      createElement("#{d.type}-section", {
        props:
          value: d.value
      })
    return createElement('div', {class: 'sections'}, children)
  components:
    'text-section': text_component
    'list-section': list_component

app = new Vue
  el: '#app'
  data:
    sections1: [
      {type: 'text', value: 'This is a text section'},
      {type: 'list', value: [
        {text: 'important', emph: true},
        {text: 'not important', emph: false},
        {text: 'important', emph: true}
      ]},
      {type: 'text', value: 'Footer'}
    ],
    sections2: [
      {type: 'text', value: 'A'},
      {type: 'text', value: 'B'},
      {type: 'text', value: 'C'},
      {type: 'list', value: [
        {text: 'one!', emph: true},
        {text: 'two', emph: false}
      ]}
    ]
  components:
    'sections': sections_component

index.css

body, html {
  padding: 0;
  margin: 0;
  height: 100%;
}


.emph {
  font-weight: bold;
}
.sections > * {
  padding: 6px;
}
.sections > *:not(:last-child) {
  border-bottom: 1px solid #CCC;
}
.sections {
  width: 300px;
  border: 1px solid #CCC;
  margin: 12px;
}