Vueの無状態コンポーネントの運用を理解し、習得する


作者:Milos Protic
前端サトシ
出典:medium
アリ雲は最近活動をしていて、2割引まで低くて、本当にお得だと思っています.この内容やリンクをクリックして参加することができます.https://promotion.aliyun.com/...
テンセントクラウドは最近活動をしていて、百種類のクラウド製品は1割引まで低くて、本条の内容あるいはリンクをクリックして参加することができます
アプリケーションのステータスとは何ですか?なぜ必要なのですか?
ステータス管理は、通常、より小さなプロジェクトでは必要ありませんが、より広い範囲にわたる場合、エンタープライズクラスのアプリケーションのほとんどが必要です.簡単に言えば、ステータスはアプリケーションが使用する最新値を含むオブジェクトです.しかし、構造的で抽象的な観点から見ると、状態は複雑で重要なものであり、きれいなアーキテクチャを構築し、注目点を強力に分離できることが明らかになります.
通常、経験に乏しい開発者は、ステータス管理のニーズを予測したり、ステータス管理をどのように実現したりするかを予測できないため、ステータス管理の重要性を理解することは難しい.ステータスベースのコンポーネントが蓄積されると、それらの間のデータ管理と共有は悪夢になります.長期的に見ると、ステータスベースのコンポーネントが多ければ多いほど、問題が発生します.
外部パケットを使用してステータス管理を行わない場合は、ステータスベースのコンポーネントをできるだけ少なく使用し、表示コンポーネントはそれらの周りに構築されたステータスを使用することが望ましい.
Vueと無状態(関数)コンポーネント
Vueの無状態コンポーネントは、実は関数コンポーネントです.しかし、関数コンポーネントは何ですか?この質問に答えるには、まず関数式プログラミングとは何かを理解しなければなりません.
プログラムをオブジェクトに分解するオブジェクト向けの方法とは異なり、関数式プログラミングはプログラムをより高度なプログラムを形成するために使用される小さな関数に分解することを奨励する.作成した関数は、外部状態に依存しないか、または変更することができ、これにより、所与の入力に対して常に同じ出力を返す別の観察結果をもたらす.
したがって、関数コンポーネントはステータスのないコンポーネントであり、変更できます.関数コンポーネントの出力は、常に指定された入力に基づいています.Vueでは、これらのコンポーネントは、所与のpropsに従って異なる出力を与える.
構文
Vueは、関数コンポーネントを定義する簡単な方法を提供します.functionalのキーワードをあげるだけでいいです.2.5.0以降では、単一ファイルコンポーネントが使用されている場合、テンプレートベースの関数コンポーネントは次のように宣言できます.


または
export default {
  functional: true,
  props: {
    // ...
  },
  render(createElement, context) {
    return createElement(
      'div', '  /     '
    )
  }
}

注:2.3.0以前のバージョンでは、関数コンポーネントが受信したい場合はproppropsオプションは必須です.2.3.0以降のバージョンでは、省略できます.propsオプションでは、すべてのコンポーネントのプロパティが自動的に暗黙的に解析されます.prop .
関数コンポーネントを使用する場合、参照はHTMLElementになります.これは、ステータスがなく、インスタンスがないためです.
関数コンポーネントに渡される唯一のデータはpropsであることに注意されたい.これらのコンポーネントは完全に無状態(応答データなし)であり、それらに伝達された任意の状態を無視し、ライフサイクルメソッド(createdmountedなど)をトリガしない.
また、これらのコンポーネントもインスタンス化されていないため、thisキーワードを使用してインスタンスにアクセスすることはできません.逆に、コンポーネントに必要なものはすべてcontextによって提供されます.render関数では、createElement法の第2のパラメータとして伝達される.
コンポーネントに必要なすべては、contextパラメータで渡されます.これは、次のフィールドを含むオブジェクトです.
  • props:すべてのpropを提供するオブジェクト
  • children:VNodeサブノードの配列
  • slots:すべてのスロットを含むオブジェクト
  • を返す関数です.
  • scopedSlots:(2.6.0+)入力されたアクティブドメインスロットを露出するオブジェクト.通常のスロットも関数として露出します.
  • data:コンポーネントに伝達するデータオブジェクト全体がcreateElementの第2のパラメータとしてコンポーネント
  • に伝達される.
  • parent:親コンポーネントへの参照
  • listeners:(2.3.0+)現在のコンポーネントに登録されているすべての親コンポーネントを含むイベントリスナーのオブジェクト.これはdataです.onの別名.
  • injections:(2.3.0+)injectオプションが使用されている場合、オブジェクトには注入すべき属性が含まれます.

  • なぜ無状態コンポーネントが必要なのか
    これまで,関数コンポーネントは無状態であることが分かってきたが,それらのコアでは実行可能な関数にすぎず,いくつかの入力を受け入れ,それに基づいて出力を提供する.
    これらの使用方法では、関数コンポーネントは関数にすぎないため、レンダリングコストも大幅に低く、レンダリングに時間がかかることなく非常に効率的であることを意味します.同時に、高次コンポーネントを考慮すると、任意の状態を必要とせず、所定のサブコンポーネントを追加の論理またはスタイルで包装する必要があります.
    次に、一般的な事例では、関数コンポーネントがこのようなタスクに非常に適している場合を示します.
    ≪インスタンス|Instance|emdw≫
    この例では、パッケージとして機能し、必要なスタイルを提供するpanelコンポーネントを作成します.サブアセンブリは、panel本体でレンダリングされます.
    export default {
      name: 'panel',
      functional: true,
      props: {
        title: String
      },
      render(createElement, context) {
        const slots = context.slots();
    
        const header = createElement('header', {
          attrs: { class: 'panel-header'}
        }, context.props.title);
        
        const body = createElement('main', {
          attrs: { class: 'panel-body'}
        }, slots.default);
    
        return createElement('section', {
          attrs: { class: 'panel' }
        }, [header, body]);
      }
    }
    

    上述したように、このコンポーネントの唯一の目的は、パネルタイトルおよびheaderの内容をそれぞれ保存するmainおよびHTML要素を有するパネル(カード)と同様のスタイルを提供することである.プロセス全体は、render関数のcreateElementパラメータを使用することによって達成される.createElementは、Vueコアで実装される仮想Domシステムの一部である.
    バーチャルDOM
    Vueは仮想DOMを確立することによって、自分が実際のDOMをどのように変えるかを追跡する.この行のコードをよく見てください.
    return createElement('h1', this.blogTitle)
    
    createElementはいったい何を返しますか?実際のDOM要素ではありませんより正確な名前はcreateNodeDescriptionである可能性があります.これは、Vueページにどのようなノードがレンダリングされる必要があるか、およびそのサブノードの説明情報が含まれているためです.このようなノードを「仮想ノード(virtual node)」と記述し、「VNode」と略記することも多い.「仮想DOM」は、Vueコンポーネントツリーによって構築されたVNodeツリー全体の呼び方です.
    义齿
    次に、createElement関数でテンプレートの機能をどのように使用するかを熟知する必要があります.ここではcreateElementが受け入れるパラメータです.
    // @returns {VNode}
    createElement(
      // {String | Object | Function}
      //    HTML    、      ,  
      // resolve            async   。   。
      'div',
    
      // {Object}
      //                。  。
      {
        // (      )
      },
    
      // {String | Array}
      //        (VNodes),  `createElement()`     ,
      //            “      ”。  。
      [
        '      ',
        createElement('h1', '    '),
        createElement(MyComponent, {
          props: {
            someProp: 'foobar'
          }
        })
      ]
    )
    

    パネルCSSのスタイルは以下の通りです.
    .panel {
      margin-bottom: .5rem
    }
    
    .panel, .panel-header {
        border: 1px solid #d3d3d3;
        border-radius: 4px;
    }
    
    .panel-header, .panel-body, .panel {
      padding: .5rem;
    }
    
    .panel-header {
      background-color:#efefef;
      color: #eeeee
    }
    

    これは単純で直接的なCSSであり、いくつかのpaddingcolorを提供している.
    サブアセンブリ
    次に、例をより生き生きとさせるために、自動車のリストを表示する2つの追加コンポーネントを作成し、もう1つは単純なlorem-ipsumのテキストコンポーネントであり、同じパネルスタイルと外観を必要とします.
    リストコンポーネント:
    export default {
      name: 'cars',
      props: {
        data: Array
      }
    }
    

    template:
    
    

    テキストコンポーネント:
    export default {
      name: 'lorem-ipsum'
    }
    

    template:
    
    

    次に示すように、利用可能なサブコンポーネントがあります.panelコンポーネントでアプリケーションにカプセル化する必要があります.

    これらのコンポーネントを使用するのは、例が簡単であるためです.実際の応用では、任意のタイプのコンポーネントであってもよい.
    完全なコード
    hmtl
    <template> <ul> <li v-for="car in data" :key="car">{{car}}</li> </ul> </template> <template> <p> , , , , , </p> </template>

    css
    body {
      padding: .5rem
    }
    
    * {
      padding: 0;
      margin:0;
      box-sizing: border-box;
    }
    
    .panel {
      margin-bottom: .5rem
    }
    
    .panel, .panel-header {
        border: 1px solid #d3d3d3;
        border-radius: 4px;
    }
    
    .panel-header, .panel-body, .panel {
      padding: .5rem;
    }
    
    .panel-header {
      background-color:#efefef;
      color: #eeeee
    }
    
    ul {
      list-style: none;
    }
    
    ul > li {
      padding: .5rem .2rem
    }
    

    js
    // the wrapper panel
    const panel = {
      functional: true,
      name: "panel",
      props: {
        title: String
      },
      render(createElement, context) {
        const slots = context.slots();
    
        const header = createElement('header', {
          attrs: { class: 'panel-header'}
        }, context.props.title);
        
        const body = createElement('main', {
          attrs: { class: 'panel-body'}
        }, slots.default);
    
        return createElement('section', {
          attrs: { class: 'panel' }
        }, [header, body]);
      }
    }
    
    // sample components
    
    const cars = {
      name: 'cars',
      template: '#cars',
      props: {
        data: Array
      }
    }
    
    const loremIpsum = {
      name: 'lorem-ipsum',
      template: '#lorem-ipsum'
    }
    
    new Vue({
      el: '.vue-app',
      components: {
        panel,
        cars,
        'lorem-ipsum': loremIpsum
      }
    });
    
    

    実行効果:
    コード配備後に存在する可能性のあるバグはリアルタイムで知ることができず、後でこれらのバグを解決するためにlogデバッグに多くの時間を費やしたので、こちらのついでに使いやすいバグ監視ツールFundebugをお勧めします.
    原文:https://itnext.io/whats-the-d...
    コミュニケーション
    干物シリーズの文章は以下のようにまとめられていて、いいスタートだと思います.お互いの勉強を歓迎します.
    https://github.com/qq449245884/xiaozhi
    紙面の制限のため、今日の分かち合いはここまでしかありません.もっと多くの内容を知りたいなら、各文章の一番下のQRコードをスキャンして、私たちの微信の公衆番号に注目して、もっと多くの情報と価値のある内容を知ることができます.
    毎回文章を整理して、普通はすべて2时までやっと寝て、1周4回ぐらい、とても苦しくて、また支持することを望んで、少し励まします