Vueで身につけなければならない開発テクニックを学ぶ

37894 ワード

vueが身につけなければならない6つの開発テクニック
  • 動的指令パラメータ
  • 同じルーティングのコンポーネント
  • を再利用する.
  • リスニングサブアセンブリのライフサイクル
  • スタイル
  • を貫通
  • 強力なrender関数
  • ロングリストパフォーマンス最適化
  • コンポーネントでのタイマーの使用および問題の破棄
  • ダイナミックコマンドパラメータ
    命令パラメータをコンポーネントに動的に渡します.ボタンコンポーネントがあり、場合によってはクリックイベントを傍受し、他の場合はhoverイベントを傍受したいとします.これがダイナミックパラメータの使用シーンです.
    <template>
    	...
    	<aButton @[someEvent]="handleSomeEvent()" />...
    </template>
    <script>
      ...
     data(){
         
        return{
         
          ...
          //     
          someEvent: someCondition ? "click" : "hover"
        }
      },
      methods: {
         
        handleSomeEvent(){
         
          //     
        }
      }  
    </script>
    

         
    同じルートのコンポーネントの再利用
    開発者がよく遭遇するのは,複数のルーティングが同じVueコンポーネントに解析されることである.問題は、Vueがパフォーマンス上の理由で、デフォルトでは共有コンポーネントは再レンダリングされず、同じコンポーネントを使用するルーティングを切り替えても変化はありません.
     const routes = [
      {
         
        path: "/a",
        component: MyComponent
      },
      {
         
        path: "/b",
        component: MyComponent
      },
    ]; ```
    

    ルーティング切り替え時にこれらのコンポーネントを再レンダリングすることを目的とする場合は、router-viewコンポーネントにkeyプロパティを指定することで実現できます.原理は、keyの値が異なり、次のレンダリングではこの2つが異なるコンポーネントとみなされるため、再びレンダリングされます.
    <template>
    	<router-view :key="$route.path"></router-view>
    </template>
    

         
    サブアセンブリのライフサイクルのリスニング
    $onを使用して、サブコンポーネントのライフサイクルフックライフサイクルフックがカスタムイベントを発行することをリスニングできます.これは、親コンポーネントがサブレベルのライフサイクルフックをリスニングできることを意味します.通常モードを使用してイベント(@event)をリスニングし、他のカスタムイベントと同様に処理できます.
         
    スタイルの透過
    開発でサードパーティ製コンポーネントスタイルを変更するのは一般的ですが、scopedプロパティのスタイル分離のため、コンポーネント内ではelement UIなどのサードパーティ製UIライブラリの変更は機能しません.ここでスタイルを貫通できます.注:cssプリプロセッサ(less/sass)で使用すると有効になります.
    >>>または/deep/を使用して、この問題を解決できます.
    外部のサードパーティUIライブラリ
    <style>
    .el-checkbox {
         
      display: block;
      font-size: 26px; .el-checkbox\_\_label {
          font-size: 16px;
      }
    }
    </style>
    

    内の名前に/deep/を付けると、3つのスタイルの変更が完了し、有効になります.グローバルスタイルには影響しません.
    <style>
    /deep/ .el-checkbox {
         
      display: block;
      font-size: 26px; .el-checkbox\_\_label {
          font-size: 16px;
      }
    }
    </style>
    

    render関数の役割:Vueは、ほとんどの場合、実用的なテンプレートでHTMLを作成することを推奨しますが、いくつかの特殊なシーンでtemplateを使用してHTMLを作成すると、levelのpropに基づいてタイトルを動的に作成するコンポーネントのように、コードが煩雑になります.
    //Parent.vue
    <Child :level="1" >hello world</Child>
    //Child.vue
    <template>
      <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>
    </template>
    
    <script>
      export default{
         
        props:["level"]
      }
    </script>
    

    明らかにtemplateはここで使うのは適切ではありません.render関数でこのコンポーネントを書き換えるのを見てみましょう.
    //Parent.vue
    <template>
      <div>
        <Child :level="1">Hello World</Child> 
      </div>
    </template>
    <script>
      export default {
         
        component:{
         
          child:{
         
            render(creatElement){
         
              return creatElement(
                'h'+this.level, //    
                {
         
                  style:{
         
                    color:'#f60'
                  }
                }, //      
                this.$slots.default //     
              ) 
            },
            props:{
         
              level:{
         
                required:true,
                type:Number
              }
            }
          }
        }
      }
    </script>
    

         
    強力なrender関数
    Vueは、ほとんどの場合、実用的なテンプレートでHTMLを作成することをお勧めしますが、いくつかの特殊なシーンでtemplateを使用してHTMLを作成すると、levelのpropに基づいてタイトルを動的に作成するコンポーネントなど、コードが煩雑になります.
    //Parent.vue
    <Child :level="1" >hello world</Child>
    //Child.vue
    <template>
      <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>
    </template>
    
    <script>
      export default{
         
        props:["level"]
      }
    </script>
    

    明らかにtemplateはここで使うのは適切ではありません.render関数でこのコンポーネントを書き換えるのを見てみましょう.
    //Parent.vue
    <template>
      <div>
        <Child :level="1">Hello World</Child> 
      </div>
    </template>
    <script>
      export default {
         
        component:{
         
          child:{
         
            render(creatElement){
         
              return creatElement(
                'h'+this.level, //    
                {
         
                  style:{
         
                    color:'#f60'
                  }
                }, //      
                this.$slots.default //     
              ) 
            },
            props:{
         
              level:{
         
                required:true,
                type:Number
              }
            }
          }
        }
      }
    </script>
    

    createElement自体も関数であり、3つのパラメータがあります.1.作成するノード:(必須){string|object|function}は、作成するHTMLラベル名であってもよいし、コンポーネントオブジェクトであってもよいし、上記のいずれかを解析する非同期関数であってもよい2.ラベルのプロパティ:(オプション)は、以下のように詳細に説明されます.
     {
          
      //  `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
      },
      },
      //      。  ,     `binding`    `oldValue`
      //   ,   Vue            。
      directives: [
        {
         
          name: 'my-custom-directive',
          value: '2',
          expression: '1 + 1',
          arg: 'foo',
          modifiers: {
         
            bar: true
          }
        }
      ],
    
    
    } 
    

    3.サブ仮想ノード:(オプション){string|array}createElement()によって構築され、文字列を使用して「テキスト仮想ノード」を生成できます.     
    ロングリストパフォーマンスの最適化
    vueはobject.definePropertyを通じてデータをハイジャックし、ビュー応答データの変化を実現することを知っていますが、一部のコンポーネントは純粋なデータ表示であり、何の変化もありません.vueをハイジャックする必要はありません.大量のデータが表示されている場合、コンポーネントの初期化時間を明らかに減らすことができます.では、vueが私たちのデータをハイジャックすることをどのように禁止しますか?object.freezeメソッドでオブジェクトをフリーズすることができ、フリーズされたオブジェクトは二度と変更できません.
    export default {
         
      data: () => ({
         
        users: {
         }
      }),
      async created() {
         
        const users = await axios.get("/api/users");
        this.users = Object.freeze(users);
      }
    };
    

    また、ここではusersの値を凍結しただけで、参照は凍結されず、reactiveデータが必要な場合はusersに値を再付与することができます.
    export default {
         
      data: () => ({
         
        users: []
      }),
      async created() {
         
        const users = await axios.get("/api/users");
        this.users = Object.freeze(users);
      },
      methods:{
         
        //            
        this.users[0] = newValue
        //              
        this.users = newArray
      }
    };
    

         
    コンポーネントでのタイマーの使用と問題の破棄
    ページAでタイマーを使用している場合、ページAからページBにジャンプしたときに、手動でタイマーをクリアしないと、まだ実行されます.これは私たちが望んでいることではありません.一般的に考えられる一般的な解決策は、dataプロパティにtimerを定義し、コードでタイマを起動し、コンポーネントが破棄されたときにタイマをクリアすることです.具体的なコードは以下の通りです.
    data(){
         
        return{
         
            timer:null
        }
    },
    methods:{
         
        onStartTimer(){
         
            this.timer = setInterval( () => {
         
                //       
            }, 1000)
        }
    },
    beforeDestroy() {
         
        clearInterval(this.timer);        
        this.timer = null;
    }
    

    しかし、ここには潜在的な問題があります.
  • このコンポーネントインスタンスにこのtimerを保存する必要がありますが、グローバルではなくローカル関数のみがアクセスできるようにするのが最善です.さもないと他のtimer
  • に誤ってぶつかる可能性があります
    解決策:Vueが公式に与えた解決策は、timerを定義する際に$once命令を使用してbeforeDestroyというフック関数を傍受することである.具体的なコードは次のとおりです.
      methods:{
         
            onStartTimer(){
         
                const timer = setInterval( () => {
         
                    //       
                }, 1000)
                this.$once('hook:beforeDestroy', () => {
                     
                    clearInterval(timer);                                    
                })
            }
        },
    

    これにより、上記の2つの問題が解決されます.この方法は、ページを離れるときに破棄する必要があるコンポーネントと同様に使用できます.