大白話Vue 2.x-render関数

11241 ワード

Vueは、ほとんどの場合templateを使用してHTMLを作成することをお勧めします.しかし、いくつかのシーンでは、JavaScriptの完全なプログラミング能力が本当に必要です.これはrender関数で、templateよりもコンパイラに近いです.
これはVueの公式文書を引用した一言で、確かに多くの場合render関数を把握する必要があり、より柔軟で変化が多いが、書き間違えやすい(よく間違えた私o(//▽//)q)、ここでrenderを勉強したノートを記録します.
Vue公式ドキュメント栗
  • templateを使用してHTML
  • を作成
    
      <div>
        <h1 v-if="level === 1">
          <slot></slot>
        </h1>
        <h2 v-if="level === 2">
          <slot></slot>
        </h2>
        <h3 v-if="level === 3">
          <slot></slot>
        </h3>
        <h4 v-if="level === 4">
          <slot></slot>
        </h4>
        <h5 v-if="level === 5">
          <slot></slot>
        </h5>
        <h6 v-if="level === 6">
          <slot></slot>
        </h6>
      </div>
    
    
  • render関数を使用してHTML
  • を作成
    Vue.component('anchored-heading', {
      render: function (createElement) {
        return createElement(
          'h' + this.level,   // tag name     
          this.$slots.default //        
        )
      },
      props: {
        level: {
          type: Number,
          required: true
        }
      }
    })
    

    公式の栗から見ると,場合によってはrender関数がtemplateよりも比べものにならない優位性があることが明らかになった.構造が複雑なhtmlや論理が多いhtmlでは、render関数を使用して作成することをお勧めします.
    理解しなければならない知識
    slot
  • Props:
  • name-string、スロットの名前を付けます.

  • Usage:
  • 要素は、コンポーネントテンプレート内のコンテンツ配信スロットとして機能する.要素自体が置き換えられます.


  • コンポーネントを組み合わせるには、親コンポーネントの内容とサブコンポーネント独自のテンプレートをブレンドする方法が必要です.このプロセスは、Angularに詳しい場合は、コンテンツ配信(または「transclusion」と呼ばれます).Vue.jsはコンテンツ配信APIを実現し,現在のWebコンポーネント仕様草案を参照し,特殊な要素を元のコンテンツのスロットとして使用する.
    slotはコンポーネントを書くときに最もよく使われていますが、その役割は何ですか?わかりやすいのは、占有率、または公式ドキュメントでいうスロットです.コンピュータのマザーボードのように、多くのスロットがあり、使用するか使用しないかを選択することができます.自分がどんなモデルとブランドを使用するかを決めることもできます.slotはこのようなスロットの役割を果たしています.
    公式栗
    
    


    slot要素は、特別な属性nameでコンテンツの配布方法を構成できます.複数のslotは異なる名前を持つことができます.名前付きslotは、コンテンツクリップにslotプロパティに対応する要素が一致します.一致するコンテンツクリップが見つからない代替スロットとして、デフォルトのslotである匿名のslotも使用できます.デフォルトのslotがない場合、一致するコンテンツクリップが見つからないと破棄されます.
    たとえば、コンピュータのマザーボードにメモリスロットがあり、独立したグラフィックススロットがある場合は、グラフィックススロットではなく1本のメモリスロットをインストールするだけで、まったく影響はありません.
    
    
    


    义齿
    createElementのパラメータは3つの部分を含む
  • 最初のパラメータはHTMLタグ文字列(必須パラメータ)
  • である.
  • の2番目のパラメータは、テンプレート関連属性を含むデータオブジェクト(空objectであってもよい)
  • である.
  • の3番目のパラメータHTMLのサブノード(空であってもよい.createElementの配列であるか、単純に文字列を使用して「テキストノード」を生成する)
  • createElement(
      // {String | Object | Function}
      //    HTML      ,      ,          String/Object   ,    
      'div',
      {
         // {Object}
        //                
        //   ,     template        .    .
      },
      [
        // {String | Array}
        //     (VNodes),  `createElement()`     ,
        //             “    ”。    。
      ]
    )
    

    完全なパラメータは次のとおりです.
    createElement(
      // {String | Object | Function}
      //    HTML       ,      ,          String/Object   ,    
      'div',
    
      // {Object}
      //                
      //   ,     template        .    .
      //         template      
      {
        //  `v-bind:class`    API
        'class': {
            foo: true,
            bar: false
        },
        //  `v-bind:style`    API
        style: {
            color: 'red',
            fontSize: '14px'
        },
        //     HTML   
        attrs: {
            id: 'foo'
        },
        //    props
        props: {
            myProp: 'bar'
        },
        // DOM   
        domProps: {
            innerHTML: 'baz'
        },
        //         `on`
        //         `v-on:keyup.enter`    
        //        keyCode。
        on: {
            click: this.clickHandler
        },
        //      ,        ,          `vm.$emit`      。
        nativeOn: {
            click: this.nativeClickHandler
        },
        //      .     :          
        // Vue        
        directives: [
            {
                name: 'my-custom-directive',
                value: '2',
                expression: '1 + 1',
                arg: 'foo',
                modifiers: {
                    bar: true
                }
            }
        ],
        // Scoped slots in the form of
        // { name: props => VNode | Array }
        scopedSlots: {
            default: props => createElement('span', props.text)
        },
        //              ,   slot     
        slot: 'name-of-slot',
        //         
        key: 'myKey',
        ref: 'myRef'
      },
      // {String | Array}
      //     (VNodes),  `createElement()`     ,
      //             “    ”。    。
      [
        '      ', //    
        createElement('h1', '    '),
        createElement(MyComponent, {
          props: {
            someProp: 'foobar'
          }
        })
      ]
    )
    

    createElementのイベントリスニング(on)は、イベント&キー修飾子を使用できます.
    じっさいかいはつ
    普段の開発では、render: h => h(App)という形式が一般的です.実はこれはhをcreateElementの別名として使うのが一般的な慣例です
    シンプルな栗
    よくある書き方
    
    Vue.component('mySelect', {
        render: (h) => {  
            //     select  
            return h('select',
                //select          
                {
                    on:{
                        'change':(val)=>{
                            
                        }
                    }
                },
                //     option
                [
                    h('option', 
                        //option          
                        {
                            domProps: {
                                value: 0,                            
                                innerHTML: ' '
                            }
                        }
                        //     ,         
                    ),
                    h('option', {
                        domProps: {
                            value: 1,                        
                            innerHTML: ' '
                        },
                    })
                ]
            )
    })  
    
    //mySelect     
    
    

    v-forサイクル
    もちろん、コンポーネントとしてはコンテンツをすべて書くことはありません.パラメータに基づいてレンダリング結果を決定する必要があります.では、V-forに相当するrenderを見てみましょう.render関数ループの作成にはmap関数を用いる必要があるが,ここではmap関数のみでデータの変化を検出することができ,他の方法ではデータの変化に応じて変化することはできないことに注意すべきである.
    Vue.component('myNewSelect', {
        // props 
        props:{  
            items:{  
                type:Array,  
                default: []
            }
        },
        render: (h) => {
            //     select  
            return h('select',
                Array.apply(null, this.items.map(function(item){  
                    return h('option',
                        {  
                            domProps: {
                                value: item.value,                            
                                innerHTML: item.name
                            },
                        })  
                    })
                )
            )
        }
    })
    
    //  
    items = [
        {
            value: 0,
            name: '   '
        },
        {
            value: 1,
            name: '   '
        },
        {
            value: 2,
            name: '   '
        },
    ]
    
    //     
    
    

    v-if判断
    次はv-ifのrender関数で、v-ifの効果を実現するのも簡単で、return前に判断するだけです.
    Vue.component('myList', {
        props:{  
            items:{  
                type:Array,  
                default: []
            }
        },
        render: (h) => {
            if(items.length > 0){
                return h('ul',
                    Array.apply(null, this.items.map(function(item){  
                        return h('li',
                            {  
                                domProps: {
                                    innerHTML: item.name
                                },
                            })  
                        })
                    )
                )
            }else{
                return h('p', '    ')
            }
        }
    })
    

    v-model双方向バインド
    render関数の双方向バインドの方法は2つあるようです(もっとあるかもしれません)
  • 親要素のデータまたはメソッド(使用に賛成しない)
  • を$parentの方法で直接操作する
  • は、親子コンポーネントの$emitによって実現する、render関数においてデータの変化を傍受し、$emitによってイベント
  • を上方に伝達する.
    次は$emitで双方向バインドを実現した栗です
    Vue.component('myInput', {
        props:{  
            value:{  
                type: String,  
                default: ''
            }
        },
        render: (h) => {
            let _this = this;
            return h('input',{
                domProps:{  
                    value:_this.value 
                },
                on: {
                    input: function (event) {
                        _this.change(event.target.value);
                    }
                }
            })
        },
        methods:{  
            change(value){  
                this.$emit('valueChange', value);
            }  
        }  
    })
    
    

    親コンポーネント
    
    
    var app=new Vue({  
        el:'#app',  
        data:{  
            value: 'default'
        },  
        methods:{  
            valueChange(value){  
                this.value = value;
            }  
        }  
    })  
    

    slotコンテンツ配信
    render関数でslotを使用するのはtemplateとあまり差がなく、h()関数でslotの名前を指定するだけで、slotの内容を直接レンダリングすることができます.render関数では、$slotsにアクセスしてすべてのslotを取得できます.
    vm.$slotsは、slotによって配布されたコンテンツにアクセスするために使用されます.各名前のslotには、対応するプロパティがあります(たとえば、slot=「foo」の内容はvm.$slots.fooで見つかります).defaultプロパティには、名前付きslotに含まれていないすべてのノードが含まれます.
  • slotの名前を指定する
  • Vue.component('mySlot', {
        render: (h) => {
            let _this = this;
            return h('div',{
                 slot: 'name-of-slot'
            })
        }
    })
    
    
  • $slotsアクセス(公式栗)
  • Vue.component('blog-post', {
      render: function (createElement) {
        var header = this.$slots.header
        var body   = this.$slots.default
        var footer = this.$slots.footer
        return createElement('div', [
          createElement('header', header),
          createElement('main', body),
          createElement('footer', footer)
        ])
      }
    })
    

    最後に
    特別な需要がなければ、やはりrender関数を振り回さないでください、おとなしくて実用的なtemplate、render関数はやはりとても人を振り回して、うっかりして間違ったことを報告しました(もちろん私の技術のかすのためです(¯▽¯;)
    リファレンス
  • vue公式ドキュメント
  • vue2.0のrender関数はどのように双方向データバインドを実現しますか?

  • 狂人のブログ