ホームページ ウェブフロントエンド jsチュートリアル Vueコンポーネントでイベントを渡す方法

Vueコンポーネントでイベントを渡す方法

Jun 14, 2018 pm 03:44 PM
vue イベント配信

最近の仕事では Vue を使用する必要があるので、私が最近触ったのは Vue です。Vue コンポーネント間のイベント転送について紹介します。必要な方は参考にしてください。新しい仕事には Vue を使用する必要があります。私が最近接した仕事も Vue です。以前は React を使用していたので、すぐに Vue を使い始めました。

また、いくつかの補助的なメソッドに加えて、この 2 つの類似点と相違点も見つけようとします。最大の違いは、コンポーネント間の通信だけでなく、イベントの監視もあります。コンポーネント間で渡されて使用されます。

しかし、vue2.+ では、vue は効率を向上させるために diff アルゴリズムと仮想 dom を導入しました。 DOM 要素の頻繁な更新に対処するために、コンポーネントを変更する必要がある場合、イベント リスナーの頻繁な変更と初期化の間に競合はありますか? それを確認するために簡単なコードを書いてみましょう。

p で作成した 2 つのボタンを記述します。1 つは HTML コードで記述され、もう 1 つはコンポーネントの形式で挿入されます。2 つのボタンはまったく同じですが、外側のレイヤーに disabled 属性を追加し、if を使用します。 -else を使用して無効を決定します。これにより、さまざまなボタンが表示されます (もちろん、通常のシナリオではこのようなコードは記述しません。ここではこの方法で特別なシナリオをシミュレートするだけであり、このシナリオがビジネスに存在するかどうかを検討します)。

<template>
 <p class="test">
 <p class="btn" v-if="disabled" @click="handleClick">可点击</p>
 <p class="btn" v-else >不可点击</p>
 <Button v-if="disabled" @clickTest="handleClick">可点击</Button>
 <Button v-else>不可点击</Button>
 </p>
</template>

<script>
import Button from &#39;./Button&#39;
export default {
 data () {
 return {
  disabled: true
 }
 },
 methods: {
 handleClick() {
  alert(&#39;可点击&#39;)
 }
 },
 components: {
 Button,
 },
 mounted() {
 setTimeout(() => {
  this.disabled = false
 }, 1000)
 }
}
</script>
<style>
.btn{
 margin: 100px auto;
 width: 200px;
 line-height: 50px;
 border: 1px solid #42b983;
 border-radius: 5px;
 color: #42b983;
}
</style>
ログイン後にコピー

できるだけ見栄えを良くするために、2 つのボタンがクリック可能な場合はクリック イベントにバインドされ、クリックできない場合はバインドされません。違いは、1 つは直接記述された HTML コードであり、もう 1 つはコンポーネントであることです。コンポーネントのコードは次のとおりです:

<template>
 <p class="btn" @click="handleClick"><slot></slot></p>
</template>
<script>
 export default {
  methods: {
   handleClick() {
    this.$emit(&#39;clickTest&#39;)
   }
  }
 }
</script>
ログイン後にコピー

次に、マウントされたサイクルに 1 秒の settimeout を追加して、disabled を false に変更し、テストしてみましょう

disabled が true のままの場合、両方のボタンはクリックするとポップアップが表示されます。 クリックアラート。ただし、disabled を false に変更すると、HTML で書かれたものはポップアップされなくなりますが、以下のコンポーネントで書かれたものは引き続きポップアップされます。

この種の問題が発生した場合、コードがこの clicktest イベントを呼び出さないことは明らかであり、ページ上ではボタンがクリックできなくなっていることも確認できるため、この種の問題を特定することは非常に困難です。では、なぜこのイベントがまだ呼び出されているのでしょうか?

diff アルゴリズムから始めましょう。 従来の差分ツリー アルゴリズムのアルゴリズムの複雑さは O(n^3) で、react が diff アルゴリズムを導入すると、レベル間の移動がなくなり、同じレベルのみを比較します。ノードの類似点と相違点により、アルゴリズムの複雑さが O(n) に軽減され、ページ全体を制約なく頻繁に (もちろん適度に) 更新できるようになります。

(笑、写真はありません)

diff の 1 つの戦略は、同じクラスを持つ 2 つのコンポーネントが同様のツリー構造を生成し、異なるクラスを持つ 2 つのコンポーネントが異なるツリー構造を生成することです。したがって、その比較順序は

1) ツリー diff

2) コンポーネント diff

3) 要素 diff

コードに戻ると、コンポーネント diff を実行するとき、それらは同じコンポーネントであると考えられ、次に要素 diff を実行します。つまり、追加、削除、移動するため、コンポーネントをインスタンス化するときにイベント リスナーを初期化しましたが、同じコンポーネント内の dom を置き換えるときに、Vue がコンポーネントに追加されたコンテンツに応答しませんでした。 . イベントリスナーが削除されます。

vue コードを見てみましょう。

Vue.prototype.$emit = function (event: string): Component {
 const vm: Component = this
 if (process.env.NODE_ENV !== &#39;production&#39;) {
  const lowerCaseEvent = event.toLowerCase()
  if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
  tip(
   `Event "${lowerCaseEvent}" is emitted in component ` +
   `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
   `Note that HTML attributes are case-insensitive and you cannot use ` +
   `v-on to listen to camelCase events when using in-DOM templates. ` +
   `You should probably use "${hyphenate(event)}" instead of "${event}".`
  )
  }
 }
 let cbs = vm._events[event]
 if (cbs) {
  cbs = cbs.length > 1 ? toArray(cbs) : cbs
  const args = toArray(arguments, 1)
  for (let i = 0, l = cbs.length; i < l; i++) {
  try {
   cbs[i].apply(vm, args)
  } catch (e) {
   handleError(e, vm, `event handler for "${event}"`)
  }
  }
 }
 return vm
 }
ログイン後にコピー

vue は、vdom の _events 属性を通じてバインドされたイベントがあるかどうかを判断します。クリックできないボタン

:
clickTest
:
Array(1)
0
:
ƒ invoker()
length
:
ログイン後にコピー

の _events を調べたところ、クリックテストがまだ存在していることがわかりました。それが問題なのです。

では、このような問題を回避するにはどうすればよいでしょうか? diff 比較によって問題を解決するべきでしょうか、それともコードを調べるべきでしょうか?

function sameVnode (a, b) {
 return (
 a.key === b.key && (
  (
  a.tag === b.tag &&
  a.isComment === b.isComment &&
  isDef(a.data) === isDef(b.data) &&
  sameInputType(a, b)
  ) || (
  isTrue(a.isAsyncPlaceholder) &&
  a.asyncFactory === b.asyncFactory &&
  isUndef(b.asyncFactory.error)
  )
 )
 )
}
ログイン後にコピー

つまり、diffの場合は、いわゆる第一判定原理が鍵となります。

key は、react が diff を導入したときに追加される属性でもあり、前後の vdom ツリーが統合された要素であるかどうかを判断するために使用されます (兄弟関係であることに注意してください)。そのため、キーをコードに追加するだけで済みます。この問題

<Button key="1" v-if="disabled" @clickTest="handleClick">可点击</Button>
<Button key="2" v-else>不可点击</Button>
ログイン後にコピー

このようにして、ボタンをクリックしてもポップアップボックスは表示されなくなります。

Key には幅広い関数があります。配列を走査して DOM を生成する場合、決定可能な一意の ID (配列インデックスは使用しないことに注意してください) を追加すると、比較効率が最適化され、必要な DOM 操作が少なくなります。また、兄弟要素の変更によって再レンダリングされないように、p にキーを追加します (このタイプの p は通常、キャンバスの生成など、react や vue 以外のイベントまたはアクションにバインドされます)。 )。

では、この不要なキー値をコンポーネントに追加する以外に、それを解決する他の方法はあるのでしょうか?

はい、非常に反 Vue ですが React に似た方法があります。これは、次のように props を介してコールバック イベントを渡すことです。

<Button v-if="disabled" :clickTest="handleClick">可点击</Button>
<Button v-else>不可点击</Button>
  props: {
   &#39;clickTest&#39;: {
    type: Function
   }
  },
  methods: {
   handleClick() {
    //this.$emit(&#39;clickTest&#39;)
    this.clickTest && this.clickTest()
   }
  }
ログイン後にコピー

虽然vue给了我们更方便的事件传递的方式,但props里是允许我们去传递任何类型的,我的期望是在真实的dom上或者在公共组件的入口处以外的地方,都是通过props的方式来传递结果的。虽然这种方式很不vue,而且也享受不到v-on给我们带来的遍历,但是这样确实可以减少不必要的麻烦。

当然既然用了vue,更好的利用vue给我们带来的便利也很重要,所以对于这种很少会出现的麻烦,我们有一个预期,并可以快速定位并修复问题,就可以了。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在vue中如何通过v-for处理数组

使用vue如何实现收藏夹

在node.js中有关npm和webpack配置方法

如何通过js将当前时间格式化?

使用vue引入css,less相关问题

以上がVueコンポーネントでイベントを渡す方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

VUEのボタンに関数を追加する方法 VUEのボタンに関数を追加する方法 Apr 08, 2025 am 08:51 AM

HTMLテンプレートのボタンをメソッドにバインドすることにより、VUEボタンに関数を追加できます。 VUEインスタンスでメソッドを定義し、関数ロジックを書き込みます。

VueでBootstrapの使用方法 VueでBootstrapの使用方法 Apr 07, 2025 pm 11:33 PM

vue.jsでBootstrapを使用すると、5つのステップに分かれています。ブートストラップをインストールします。 main.jsにブートストラップをインポートしますブートストラップコンポーネントをテンプレートで直接使用します。オプション:カスタムスタイル。オプション:プラグインを使用します。

vue.jsでJSファイルを参照する方法 vue.jsでJSファイルを参照する方法 Apr 07, 2025 pm 11:27 PM

vue.jsでJSファイルを参照するには3つの方法があります。タグ;; mounted()ライフサイクルフックを使用した動的インポート。 Vuex State Management Libraryを介してインポートします。

VueでWatchの使用方法 VueでWatchの使用方法 Apr 07, 2025 pm 11:36 PM

Vue.jsの監視オプションにより、開発者は特定のデータの変更をリッスンできます。データが変更されたら、Watchはコールバック関数をトリガーして更新ビューまたはその他のタスクを実行します。その構成オプションには、すぐにコールバックを実行するかどうかを指定する即時と、オブジェクトまたは配列の変更を再帰的に聴くかどうかを指定するDEEPが含まれます。

Vueによる前のページに戻る方法 Vueによる前のページに戻る方法 Apr 07, 2025 pm 11:30 PM

vue.jsには、前のページに戻る4つの方法があります。$ router.go(-1)$ router.back()outes&lt; router-link to =&quot;/&quot; Component Window.history.back()、およびメソッド選択はシーンに依存します。

Vueはマーキー/テキストスクロール効果を実現します Vueはマーキー/テキストスクロール効果を実現します Apr 07, 2025 pm 10:51 PM

CSSアニメーションまたはサードパーティライブラリを使用して、VUEでマーキー/テキストスクロール効果を実装します。この記事では、CSSアニメーションの使用方法を紹介します。スクロールテキストを作成し、テキストを&lt; div&gt;をラップします。 CSSアニメーションを定義し、オーバーフローを設定します:非表示、幅、アニメーション。キーフレームを定義し、アニメーションの開始と終了時にtranslatex()を設定します。期間、スクロール速度、方向などのアニメーションプロパティを調整します。

Function Intercept Vueの使用方法 Function Intercept Vueの使用方法 Apr 08, 2025 am 06:51 AM

VUEの関数傍受は、指定された期間内に関数が呼び出され、パフォーマンスの問題を防ぐ回数を制限するために使用される手法です。実装方法は次のとおりです。LodashLibrary:Import {Debounce}から「Lodash」からインポート。 debounce関数を使用して、インターセプト関数を作成します。インターセプト関数を呼び出すと、制御関数は500ミリ秒でせいぜい1回呼び出されます。

Vue Multi-Page開発とはどういう意味ですか? Vue Multi-Page開発とはどういう意味ですか? Apr 07, 2025 pm 11:57 PM

VUEマルチページ開発は、VUE.JSフレームワークを使用してアプリケーションを構築する方法です。アプリケーションは別々のページに分割されます。コードメンテナンス:アプリケーションを複数のページに分割すると、コードの管理とメンテナンスが容易になります。モジュール性:各ページは、簡単に再利用および交換するための別のモジュールとして使用できます。簡単なルーティング:ページ間のナビゲーションは、単純なルーティング構成を介して管理できます。 SEOの最適化:各ページには独自のURLがあり、SEOに役立ちます。

See all articles