ホームページ >ウェブフロントエンド >Vue.js >v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

青灯夜游
青灯夜游転載
2022-01-29 09:00:303409ブラウズ

Vue の v-model を通じて双方向バインディングが実装されていない場合はどうなりますか?以下の記事ではv-modelを使わずに双方向バインディングを実現する方法を紹介していますので、ご参考になれば幸いです。

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

#v-model を使用せずに双方向バインディングを実現するにはどうすればよいですか?

そんな初歩的な質問をするなんて神経がいると言う人もいますが?

言わないでください、私が初めて vue を学んだとき、これらの問題に死ぬほど苦しみました。必死で公式 Web サイトのドキュメントのデモに従って書きました。使えるようになった後、私は私も日々の開発で v-model をたくさん書いていましたが、関連するバグを注意深く研究することに決めた後、まだ多くの方法があることに気づきました。 [関連する推奨事項: vue.js ビデオ チュートリアル ]

まず答えを見てみましょう:

<template>
  <div class="test-v-model">
    <p>使用v-model</p>
    <input v-model="msg" placeholder="edit me" />
    <p>{{ msg }}</p>

    <p>不使用v-model</p>
    <input :value="msg1" @input="handleInput" placeholder="edit me" />
    <p>{{ msg1 }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;test-v-model&#39;,
  data() {
    return {
      msg: &#39;&#39;,
      msg1: &#39;&#39;
    }
  },
  methods: {
    handleInput(e) {
      this.msg1 = e.target.value
    }
  }
}
</script>

Do not v-model を使用する場合、双方向バインディングを実現するには、value 属性を通じて値をバインドし、入力イベントを通じてバインディング値を変更する必要があります。

つまり、v-model は単なる省略形です

実際、v-model の本質は糖衣構文であり、ユーザー入力イベントを監視して更新する役割を果たします。データを作成し、極端なシーンで特別な処理を実行します。 -- 公式ドキュメント

v-model は、内部的にさまざまな入力要素に対してさまざまなプロパティを使用し、さまざまなイベントをスローします。

  • text 要素と textarea 要素 value を使用します。 プロパティと input イベント;
  • チェックボックスとラジオは、checked プロパティと change イベントを使用します;
  • selectフィールドにはプロパティとして value が、イベントとして change が含まれます。
#この質問に関連するナレッジ拡張機能

    双方向バインディング
  • 一方向データ バインディング
  • vue コンポーネント

#Q: 双方向バインディングとは何ですか?

#双方向バインディングとは、データが変更されると、ビューが同期的に更新されることを意味します。ビューが変更されると、データも更新されます。

Q: 一方向データ バインディングとは何ですか?

一方向データ バインディングとは、データが変更されたときを意味します。 、ビューは同期的に更新され、ビューが変更されてもデータは更新されません。

vue では、双方向バインディングは

v-model 命令を通じて実現され、一方向データ バインディングは v-bind# を通じて実現されます。 ##次のコードと、このコードを実行する gif デモを読むと、それらの違いを理解できるようになります。

<template>
  <div>
    <p>双向绑定</p>
    <input v-model="msg" placeholder="edit me" />
    <p>{{ msg }}</p>

    <p>单向数据绑定</p>
    <input v-bind:value="msg1" placeholder="edit me" />
    <p>{{ msg1 }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;test-v-model&#39;,
  data() {
    return {
      msg: &#39;&#39;,
      msg1: &#39;&#39;
    }
  }
}
</script>

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。gif 図からわかるように、v-model を使用すると、データが変更されると、ビューが同期的に更新されます。ビューが変更されると、データも更新されます。これは双方向バインディングです。

v-bind を使用すると、データが変更されると、ビューが同期的に更新されます。ビューが変更されても、データは更新されません。これは一方向のデータ バインディングです。

Q: vue の一方向データ フローとは何ですか?

子コンポーネントは、親コンポーネントによって渡された prop 属性を変更できません。推奨されるアプローチは、イベントをスローし、親コンポーネントに境界を変更するように通知することです。それ自体の価値。
要約すると、データは減少し、イベントは増加します。


vue ドキュメントでは、Prop. を導入する際に一方向データ フローの概念を提唱しています。
ここをクリック

すると、vue ドキュメントの一方向データ フローの説明が表示されます。

すべてのプロパティは、親プロパティと子プロパティの間で
一方向の下向きバインディングを形成します

: 親プロパティの更新は子コンポーネントに下向きに流れますが、その逆になります。不可能である。これにより、子コンポーネントが親コンポーネントの状態を誤って変更して、アプリケーションのデータ フローが理解しにくくなるのを防ぐことができます。

さらに、親コンポーネントが変更されるたびに、子コンポーネント内のすべてのプロパティが最新の値に更新されます。これは、子コンポーネント内の props を
変更すべきではないということを意味します。これを行うと、Vue はブラウザーのコンソールに警告を発行します。

次の例を見てみましょう:

サブコンポーネントは、prop 値に対して双方向のバインディングを直接実行します。

親コンポーネント コード:

<template>
  <child-component :value="fatherValue" />
</template>

<script>
import ChildComponent from &#39;./child.vue&#39;

export default {
  name: &#39;father-component&#39;,
  components: {
    ChildComponent
  },
  data() {
    return {
      fatherValue: &#39;&#39;
    }
  }
}
</script>

子コンポーネント コード:

<template>
  <div class="child-component">
    <input v-model="value" placeholder="edit me" />
    <p>{{ value }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;child-component&#39;,
  props: {
    value: {
      type: String,
      default: &#39;&#39;
    }
  }
}
</script>

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

可以看到,childComponent中的 prop 值可以实现双向绑定,但是 FatherComponent 中的 data 值并未发生改变,而且控制台抛出了警告:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"

翻译一下:避免直接改变 prop 值,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于 prop 值的 data 或 computed。

很显然,直接改变子组件的 prop 值的这种行为被 vue 禁止了。

如何操作传入子组件的 prop 值

但是很多时候,我们确实要操作传入子组件的 prop 值,该怎么办呢?

正如上面的警告所说,有两种办法:

  • 这个 prop 用来传递一个初始值,定义一个本地的 data property 并将这个 prop 用作其初始值
props: {
  initialCounter: {
    type: Number,
    default: 0
  },
},
data() {
  return {
    counter: this.initialCounter
  }
}
  • 这个 prop 以一种原始的值传入且需要进行转换,用这个 prop 的值来定义一个计算属性
props: {
  size: {
    type: String,
    default: &#39;&#39;
  }
},
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

这样不管怎么操作数据都是操作的子组件数据了,不会影响到父组件数据。

所以,我们想用 prop 传入的数据实现双向绑定,可以这么写:

父组件代码不变

子组件里用 innerValue 来接收传入的 value :

<template>
  <div class="child-component">
    <input v-model="innerValue" placeholder="edit me" />
    <p>{{ innerValue }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;child-component&#39;,
  props: {
    value: {
      type: String,
      default: &#39;&#39;
    }
  },
  data() {
    return {
      innerValue: this.value
    }
  }
}
</script>

这里要注意一个问题

在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。

还是上面的例子,我们将传入的值改为对象:

父组件代码:

<template>
  <child-component :obj="fatherObj" />
</template>

<script>
import ChildComponent from &#39;./child.vue&#39;

export default {
  name: &#39;father-component&#39;,
  components: {
    ChildComponent
  },
  data() {
    return {
      fatherObj: {
        name: &#39;lin&#39;
      }
    }
  }
}
</script>

子组件代码:

<template>
  <div class="child-component">
    <input v-model="innerObj.name" placeholder="edit me" />
    <p>{{ innerObj.name }}</p>
  </div>
</template>

<script>
export default {
  name: &#39;child-component&#39;,
  props: {
    obj: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      innerObj: this.obj
    }
  }
}
</script>

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

这里的 this.obj 是引用类型,赋值给了 innerObj,所以 innerObj 实际上还是指向了父组件的数据,对 innerObj.name 的修改依然会影响到父组件

所以,处理这种引用类型数据的时候,需要深拷贝一下

import { clone } from &#39;xe-utils&#39;
export default {
  name: &#39;child-component&#39;,
  props: {
    obj: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      innerObj: clone(this.obj, true)
    }
  }
}

v-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。

如上图所示,这样子组件和父组件之间的数据就不会互相影响了。

总结

至此,终于把双向绑定和单向数据流讲清楚了,真的没想到,平时开发时都懂的概念,想讲清楚居然花了这么多篇幅,确实不容易,不过,这也是对自己的一种锻炼吧。

问:v-model是双向绑定吗?

是,但只是语法糖

问:v-model是单向数据流吗?

是,数据向下,事件向上

本题还有一些其他问法,比如:

  • vue 的双向绑定和单向数据流有什么区别?
  • 为什么说 vue 的双向绑定和单向数据流不冲突?

看完本篇文章,相信不管怎么问,你都能对这两个概念理解透彻了。

更多编程相关知识,请访问:编程入门!!

以上がv-model を使用せずに Vue で双方向バインディングを実装する方法について話しましょう。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。