ベストプラクティス:vue弾窓およびスライダ応答式

23932 ワード

下記は項目中の弾窓/スライダ統一処理方式まとめ(下記el-dialogを例に挙げる)
プレゼンテーション環境:https://eugvd.csb.app/Demoアドレス:https://codesandbox.io/s/thirsty-sun-eugvd?file=/src/components/User.vue:2122-2497
DOM構造
方式1.(推奨1:直接データ注入「詳細」)el-dialogシェルは外にあり、内容は個別のコンポーネントであり、後続のコンポーネントは他のシェルに置き換えることができる
<template>
  <el-dialog
    title="  "
    :visible.sync="centerDialogVisible"
    width="30%"
    center>

    
    <my-component :visible.sync="centerDialogVisible" :data="xxxx">my-component>

    
    <span slot="footer">
      <el-button @click="centerDialogVisible = false">   el-button>
      <el-button type="primary" @click="centerDialogVisible = false">   el-button>
    span>
  el-dialog>
template>

方式2.(推奨2)el-dialogシェルは外にあり、内容は個別のコンポーネントであり、後続のコンポーネントは他のシェルに置き換えることができる.
<template>
  <el-dialog
    title="  "
    :visible.sync="centerDialogVisible"
    width="30%"
    center>

    
    <my-component :visible.sync="centerDialogVisible" :id="editId">my-component>
  el-dialog>
template>

方式3.(推奨しない)el-dialogコンポーネント内部

<my-component :visible.sync="centerDialogVisible" :id="editId">my-component>

レスポンスモード
前提:コンポーネント内でデータを要求しない–推奨1:直接データを注入する「詳細」
現在のrowまたはコンポーネント外でデータを取得する場合は、本明細書で説明する範囲外で直接伝達すればよい(詳細は通常、このようなシーンである).
例:新規/編集は同じコンポーネントを使用します.(推奨2)el-dialogシェルは外にあり、コンテンツは個別のコンポーネントで、後続のコンポーネントは他のシェルに置き換えることができます.
質問:
  • データはトリガ要求に応答する、特に同一ID及び区別新規(要求不要)/編集状況
  • に注意する.
  • フォームエラープロンプト語がクリアされ、特に最初の呼び出し時に$refs['xxx']がまだ存在しない可能性があることに注意する.
    イニシアチブ
    シナリオ1.(無効)v-if + created/mounted書き方は簡単ですが、性能が非常に悪く、やむを得ず使用を根絶しました!!!
    シナリオ2.(推奨しない):keyは性能的にv-ifよりずっと良いですが、ここのシーンでは、データ応答が解決され、DOM(仮想DOM)とはあまり関係ありません.
    <my-component :visible.sync="centerDialogVisible" :id="editId" :key="editId">my-component>
    

    シナリオ3.(推奨しない)refs.xxx.init()呼び出し.2つの問題:最初の呼び出しタイミングは、await this.$nextTick()が必要になることが多い.コンポーネントの内部メソッドは外部要素によって呼び出され、結合度が高く、メンテナンスとアップグレードのコストを制御できません.
    シナリオ4.idの変更を傍受し、idの要求に従ってデータ編集保存に成功し、現在の行をクリックすると、idは変更されず、データが変更前の=>>保存に成功した後、id = undefined、キャンセルまたはクローズは処理されません.
    props: ['id'],
    watch: {
      id: {
        handler (val, oldVal) {
          //   id undefined
          if (val) {
            this.requestData(val) //     
          }
        },
        immediate: true
      },
      visible: {
        handler (val, oldVal) {
         	!val && this.resetForm()
        },
        immediate: true
      }
    }
    
  • の利点:要求が正確で、追加の要求は存在しない
  • 劣勢:idとwatchを傍受する必要があり、処理がやや複雑な
  • シナリオ5.傍受visibleが変更され、visibleに従ってデータが要求される
    props: ['id', 'visible'],
    watch: {
      visible: {
      	handler(val, oldVal) {
      		!val && this.resetForm()
      		if (val && this.id) {
      			this.getUserById()
         }
       },
       immediate: true
      }
    }
    
  • 利点:エラーメッセージのクリア、統一処理、簡単な
  • を実現
  • 劣勢:同じID編集で、1回目は保存しない(情報は変化していない)、2回目は開いても
  • を要求する.
    補足:上記「シナリオ5」に対して、切替IDポップアップ表示状態が変化しないため、同時にIDを傍受する必要がある.
    下記はwatch functionの形式を採用している.ここでは同時にcomputed + watch形式を採用することができる
    created() {
      this.unwatch = this.$watch(
        () => {
        	return [this.id, this.visible];
        },
        (val, oldVal) => {
          let [id, visible] = val
          !visible && this.resetForm();
          if (visible && id) {
          	this.getUserById();
          }
        },
        {
        	immediate: true
        }
      );
    },
    beforeDestroy () {
    	this.unwatch()
    }
    

    えんちょうもんだい
    編集は新規と同じポップアップウィンドウで、編集してから新規に追加します.現在のポップアップウィンドウはv-show形式であるため、保存時に余分な属性がコミットされます(IDなど).特に、el-form resetFields()はシーンを処理するものではなく、el-form-item propプロパティ値のみをリセットします.
    シナリオ1:(煩雑)formオブジェクトをJSONシーケンス番号と逆シーケンス(コピー)する
    const userForm = {
      name: "",
      province: ""
    }
    export default {
      name: "User",
      props: ["visible", "id"],
      data() {
        return {
          userForm: JSON.parse(JSON.stringify(userForm)),
          rules: { ... }
        };
      },
      methods: {
      	resetForm() {
          this.$refs.userForm.resetFields();
          this.userForm = JSON.parse(JSON.stringify(userForm));
        }
      }
    }
    

    シナリオ2:(制限)コミット時にidを削除する(編集が新規属性よりも多くなると冗長になる)
    //        「  」  「  」  
    delete this.userForm.id
    ...
    

    シナリオ3:(推奨)this.$options.data()で還元
    resetForm() {
      this.$refs.userForm.resetFields();
      this.userForm = Object.assign({}, this.$options.data().userForm);
    }
    
    //     ,     this   
    const data = this.$options.data()
    Object.keys(data).forEach(key => {
      this[key] = data[key]
    })
    

    リファレンスアドレス
  • Add a function to reset a component’s state–Vue公式Issues、そのうち特に大きな返事
  • el-form-itemとformクリア値全体の問題–ElementUI公式Issues