目次
結合関数とは
マウス トラッカーの例
名前付け
結合関数の規約では、キャメル ケースの名前付けを使用し、「use」で始めることです。
その応答性は ref に依存しませんが、合成された関数は引き続き ref パラメータを受け取ることができます。他の開発者が使用する合成関数を作成している場合は、単なる生の値ではなく、ref 互換性を備えた入力パラメーターを処理することをお勧めします。この場合、unref() ユーティリティ関数が非常に役立ちます。
結合関数で
副作用
使用限制
通过抽取组合式函数改善代码结构
选项式API中使用组合式函数
与其他模式的比较
和Mixin的对比
和无渲染组件的对比
和React Hooks的对比
ホームページ ウェブフロントエンド Vue.js Vue3の関数を組み合わせたプログラミング手法とは何ですか

Vue3の関数を組み合わせたプログラミング手法とは何ですか

May 11, 2023 am 08:49 AM
vue3

結合関数とは

Vue アプリケーションの概念における「結合可能な関数」(Composables) は、Vue の結合 API を使用してステートフル ロジックをカプセル化して再利用する関数です。

フロントエンド アプリケーションを構築するとき、多くの場合、一般的なタスクのロジックを再利用する必要があります。たとえば、さまざまな場所で時刻を書式設定するために、再利用可能な日付書式設定関数を抽出できます。この関数はステートレス ロジックをカプセル化します。入力を受け取り、必要な出力を即座に返します。 lodash や date-fns など、ステートレス ロジックを再利用するライブラリは、皆さんも使用したことがあるかもしれません。

対照的に、ステートフル ロジックは、時間の経過とともに変化する状態を管理します。簡単な例は、ページ上の現在のマウス位置を追跡することです。実際のアプリケーションでは、タッチ ジェスチャやデータベースへの接続ステータスなど、より複雑なロジックが使用されることもあります。

マウス トラッカーの例

結合された API をコンポーネント内で直接使用してマウス トラッキング機能を実装すると、次のようになります:

<script setup>
import { ref, onMounted, onUnmounted } from &#39;vue&#39;
const x = ref(0)
const y = ref(0)
function update(event) {
  x.value = event.pageX
  y.value = event.pageY
}
onMounted(() => window.addEventListener(&#39;mousemove&#39;, update))
onUnmounted(() => window.removeEventListener(&#39;mousemove&#39;, update))
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>
ログイン後にコピー

ただし、同じロジックを複数のコンポーネントで再利用する場合はどうでしょうか?このロジックは、結合関数の形式で外部ファイルに抽出できます:

// mouse.js
import { ref, onMounted, onUnmounted } from &#39;vue&#39;
// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)
  // 组合式函数可以随时更改其状态。
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }
  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener(&#39;mousemove&#39;, update))
  onUnmounted(() => window.removeEventListener(&#39;mousemove&#39;, update))
  // 通过返回值暴露所管理的状态
  return { x, y }
}
ログイン後にコピー

コンポーネント内での使用方法は次のとおりです:

<script setup>
import { useMouse } from &#39;./mouse.js&#39;
const { x, y } = useMouse()
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>
ログイン後にコピー

Vue3の関数を組み合わせたプログラミング手法とは何ですか

#Asご覧のとおり、コア ロジックはまったく同じで、これを外部関数に移動し、公開する必要がある状態を返すだけです。コンポーネントと同様に、すべての合成 API を合成関数で使用できます。

useMouse() の機能は、どのコンポーネントでも簡単に再利用できるようになりました。

さらに優れているのは、複数の結合関数をネストできることです。結合関数は 1 つ以上の他の結合関数を呼び出すことができます。これにより、複数のコンポーネントを組み合わせてアプリケーション全体を形成するのと同じように、複数のより小さく論理的に独立したユニットを組み合わせて複雑なロジックを形成することができます。実際、まさにこれが、このデザイン パターンを実装する API のコレクションをコンポーザブル API と呼ぶことにした理由です。

たとえば、DOM イベント リスナーの追加とクリアのロジックを結合関数にカプセル化できます。

// event.js
import { onMounted, onUnmounted } from &#39;vue&#39;
export function useEventListener(target, event, callback) {
  // 如果你想的话,
  // 也可以用字符串形式的 CSS 选择器来寻找目标 DOM 元素
  onMounted(() => target.addEventListener(event, callback))
  onUnmounted(() => target.removeEventListener(event, callback))
}
ログイン後にコピー

これを使用すると、前の

useMouse() 結合関数

// mouse.js
import { ref } from &#39;vue&#39;
import { useEventListener } from &#39;./event&#39;
export function useMouse() {
  const x = ref(0)
  const y = ref(0)
  useEventListener(window, &#39;mousemove&#39;, (event) => {
    x.value = event.pageX
    y.value = event.pageY
  })
  return { x, y }
}
ログイン後にコピー

TIP

useMouse() を呼び出す各コンポーネント インスタンスは、独自の一意の x, y# を作成します。 ## ステータスはコピーされるため、相互に影響を与えることはありません。 非同期状態の例

useMouse()

結合関数はパラメーターを受け取らないため、1 つのパラメーターを受け取る必要がある結合関数の別の例を見てみましょう。非同期データリクエストを行うときは、ロード、ロード成功、ロード失敗などのさまざまな状態を処理する必要があることがよくあります。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>&lt;script setup&gt; import { ref } from &amp;#39;vue&amp;#39; const data = ref(null) const error = ref(null) fetch(&amp;#39;...&amp;#39;) .then((res) =&gt; res.json()) .then((json) =&gt; (data.value = json)) .catch((err) =&gt; (error.value = err)) &lt;/script&gt; &lt;template&gt; &lt;div v-if=&quot;error&quot;&gt;Oops! Error encountered: {{ error.message }}&lt;/div&gt; &lt;div v-else-if=&quot;data&quot;&gt; Data loaded: &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;{{ data }}</pre><div class="contentsignin">ログイン後にコピー</div></div> </div> <div v-else>Loading...</div> </template></pre>データを取得する必要があるすべてのコンポーネントでこのパターンを繰り返すのは面倒すぎます。これを結合関数に抽出しましょう:

// fetch.js
import { ref } from &#39;vue&#39;
export function useFetch(url) {
  const data = ref(null)
  const error = ref(null)
  fetch(url)
    .then((res) => res.json())
    .then((json) => (data.value = json))
    .catch((err) => (error.value = err))
  return { data, error }
}
ログイン後にコピー

今必要なのはコンポーネント内だけです:

<script setup>
import { useFetch } from &#39;./fetch.js&#39;
const { data, error } = useFetch(&#39;...&#39;)
</script>
ログイン後にコピー

useFetch()

静的 URL 文字列を入力として受け取ります。リクエストを 1 回実行すると完了します。しかし、URL が変更されるたびに再リクエストしたい場合はどうすればよいでしょうか?次に、パラメータとして ref を同時に受信できるようにすることができます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// fetch.js import { ref, isRef, unref, watchEffect } from &amp;#39;vue&amp;#39; export function useFetch(url) { const data = ref(null) const error = ref(null) function doFetch() { // 在请求之前重设状态... data.value = null error.value = null // unref() 解包可能为 ref 的值 fetch(unref(url)) .then((res) =&gt; res.json()) .then((json) =&gt; (data.value = json)) .catch((err) =&gt; (error.value = err)) } if (isRef(url)) { // 若输入的 URL 是一个 ref,那么启动一个响应式的请求 watchEffect(doFetch) } else { // 否则只请求一次 // 避免监听器的额外开销 doFetch() } return { data, error } }</pre><div class="contentsignin">ログイン後にコピー</div></div>このバージョンの

useFetch()

は、静的 URL 文字列と URL 文字列 ref の両方を受信できるようになりました。 isRef() を介して URL が動的参照であることを検出すると、watchEffect() を使用してリアクティブ効果を開始します。エフェクトはすぐに実行され、その過程で URL の参照が依存関係として追跡されます。 URL の参照が変更されると、データはリセットされ、リクエストが再度実行されます。 規約とベスト プラクティス

名前付け

結合関数の規約では、キャメル ケースの名前付けを使用し、「use」で始めることです。

入力パラメータ

その応答性は ref に依存しませんが、合成された関数は引き続き ref パラメータを受け取ることができます。他の開発者が使用する合成関数を作成している場合は、単なる生の値ではなく、ref 互換性を備えた入力パラメーターを処理することをお勧めします。この場合、unref() ユーティリティ関数が非常に役立ちます。

import { unref } from &#39;vue&#39;
function useFeature(maybeRef) {
  // 若 maybeRef 确实是一个 ref,它的 .value 会被返回
  // 否则,maybeRef 会被原样返回
  const value = unref(maybeRef)
}
ログイン後にコピー

組み合わせた関数が ref をパラメータとして受け取るときにリアクティブ効果を生成する場合は、必ず

watch()

を使用してください。スタイルでこの ref をリッスンすることを表示するか、正しい追跡のために watchEffect()unref() を呼び出します。 戻り値

結合関数で

reactive()

の代わりに ref() を使用していることに気づいたかもしれません。私たちが推奨する規則は、合成関数が常に複数の ref を含むプレーンな非リアクティブ オブジェクトを返すことです。これにより、オブジェクトはコンポーネント内の ref に構造化された後も応答性を維持します。 js

// x 和 y 是两个 ref
const { x, y } = useMouse()
ログイン後にコピー

Returning合成関数からのリアクティブ オブジェクトにより、オブジェクトの構造化中に合成関数内の状態へのリアクティブ接続が失われます。対照的に、ref はこの応答性の高い接続を維持します。

如果你更希望以对象属性的形式来使用组合式函数中返回的状态,你可以将返回的对象用reactive()包装一次,这样其中的 ref 会被自动解包,例如:

const mouse = reactive(useMouse())
// mouse.x 链接到了原来的 x ref
console.log(mouse.x)
ログイン後にコピー
Mouse position is at: {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->{ mouse.x }}, {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->{ mouse.y }}
ログイン後にコピー

副作用

在组合式函数中的确可以执行副作用 (例如:添加 DOM 事件监听器或者请求数据),但请注意以下规则:

  • 如果你的应用用到了服务端渲染(SSR),请确保在组件挂载后才调用的生命周期钩子中执行 DOM 相关的副作用,例如:onMounted()。这些钩子仅会在浏览器中被调用,因此可以确保能访问到 DOM。

  • 确保在onUnmounted()时清理副作用。举例来说,如果一个组合式函数设置了一个事件监听器,它就应该在onUnmounted()中被移除 (就像我们在useMouse()示例中看到的一样)。当然也可以像之前的useEventListener()示例那样,使用一个组合式函数来自动帮你做这些事。

使用限制

组合式函数在<script setup>setup()钩子中,应始终被同步地调用。在某些场景下,你也可以在像onMounted()这样的生命周期钩子中使用他们。

这个限制是为了让 Vue 能够确定当前正在被执行的到底是哪个组件实例,只有能确认当前组件实例,才能够:

  • 将生命周期钩子注册到该组件实例上

  • 将计算属性和监听器注册到该组件实例上,以便在该组件被卸载时停止监听,避免内存泄漏。

TIP

<script setup>是唯一在调用await之后仍可调用组合式函数的地方。编译器会在异步操作之后自动为你恢复当前的组件实例。

通过抽取组合式函数改善代码结构

抽取组合式函数不仅是为了复用,也是为了代码组织。随着组件复杂度的增高,你可能会最终发现组件多得难以查询和理解。组合式 API 会给予你足够的灵活性,让你可以基于逻辑问题将组件代码拆分成更小的函数:

<script setup>
import { useFeatureA } from &#39;./featureA.js&#39;
import { useFeatureB } from &#39;./featureB.js&#39;
import { useFeatureC } from &#39;./featureC.js&#39;
const { foo, bar } = useFeatureA()
const { baz } = useFeatureB(foo)
const { qux } = useFeatureC(baz)
</script>
ログイン後にコピー

在某种程度上,你可以将这些提取出的组合式函数看作是可以相互通信的组件范围内的服务。

选项式API中使用组合式函数

如果你正在使用选项式 API,组合式函数必须在setup()中调用。且其返回的绑定必须在setup()中返回,以便暴露给this及其模板:

import { useMouse } from &#39;./mouse.js&#39;
import { useFetch } from &#39;./fetch.js&#39;
export default {
  setup() {
    const { x, y } = useMouse()
    const { data, error } = useFetch(&#39;...&#39;)
    return { x, y, data, error }
  },
  mounted() {
    // setup() 暴露的属性可以在通过 `this` 访问到
    console.log(this.x)
  }
  // ...其他选项
}
ログイン後にコピー

与其他模式的比较

和Mixin的对比

Vue 2 的用户可能会对mixins选项比较熟悉。它也让我们能够把组件逻辑提取到可复用的单元里。然而 mixins 有三个主要的短板:

  • 不清晰的数据来源:当使用了多个 mixin 时,实例上的数据属性来自哪个 mixin 变得不清晰,这使追溯实现和理解组件行为变得困难。这也是我们推荐在组合式函数中使用 ref + 解构模式的理由:让属性的来源在消费组件时一目了然。

  • 命名空间冲突:多个来自不同作者的 mixin 可能会注册相同的属性名,造成命名冲突。若使用组合式函数,你可以通过在解构变量时对变量进行重命名来避免相同的键名。

  • 隐式的跨 mixin 交流:多个 mixin 需要依赖共享的属性名来进行相互作用,这使得它们隐性地耦合在一起。而一个组合式函数的返回值可以作为另一个组合式函数的参数被传入,像普通函数那样。

基于上述理由,我们不再推荐在 Vue 3 中继续使用 mixin。保留该功能只是为了项目迁移的需求和照顾熟悉它的用户。

和无渲染组件的对比

在组件插槽一章中,我们讨论过了基于作用域插槽的无渲染组件。我们甚至用它实现了一样的鼠标追踪器示例。

组合式函数相对于无渲染组件的主要优势是:组合式函数不会产生额外的组件实例开销。当在整个应用中使用时,由无渲染组件产生的额外组件实例会带来无法忽视的性能开销。

我们推荐在纯逻辑复用时使用组合式函数,在需要同时复用逻辑和视图布局时使用无渲染组件。

和React Hooks的对比

如果你有 React 的开发经验,你可能注意到组合式函数和自定义 React hooks 非常相似。组合式 API 的一部分灵感正来自于 React hooks,Vue 的组合式函数也的确在逻辑组合能力上与 React hooks 相近。然而,Vue 的组合式函数是基于 Vue 细粒度的响应性系统,这和 React hooks 的执行模型有本质上的不同。

以上がVue3の関数を組み合わせたプログラミング手法とは何ですかの詳細内容です。詳細については、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衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

vue3 プロジェクトで tinymce を使用する方法 vue3 プロジェクトで tinymce を使用する方法 May 19, 2023 pm 08:40 PM

tinymce はフル機能のリッチ テキスト エディター プラグインですが、tinymce を vue に導入するのは他の Vue リッチ テキスト プラグインほどスムーズではありません。tinymce 自体は Vue には適しておらず、@tinymce/tinymce-vue を導入する必要があります。外国のリッチテキストプラグインであり、中国語版を通過していないため、公式 Web サイトから翻訳パッケージをダウンロードする必要があります (ファイアウォールをバイパスする必要がある場合があります)。 1. 関連する依存関係をインストールします npminstalltinymce-Snpminstall@tinymce/tinymce-vue-S2. 中国語パッケージをダウンロードします 3. スキンと中国語パッケージを導入します. プロジェクトのパブリック フォルダーに新しい tinymce フォルダーを作成し、

Vue3 でページの部分的なコンテンツを更新する方法 Vue3 でページの部分的なコンテンツを更新する方法 May 26, 2023 pm 05:31 PM

ページの部分的な更新を実現するには、ローカル コンポーネント (dom) の再レンダリングを実装するだけで済みます。 Vue でこの効果を実現する最も簡単な方法は、v-if ディレクティブを使用することです。 Vue2 では、v-if 命令を使用してローカル dom を再レンダリングすることに加えて、新しい空のコンポーネントを作成することもできます。ローカル ページを更新する必要がある場合は、この空のコンポーネント ページにジャンプしてから、再びジャンプします。 beforeRouteEnter ガードを空白のコンポーネントに配置します。元のページ。以下の図に示すように、Vue3.X の更新ボタンをクリックして赤枠内の DOM を再読み込みし、対応する読み込みステータスを表示する方法を示します。 Vue3.X の scriptsetup 構文のコンポーネントのガードには o しかないので、

vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 May 21, 2023 pm 03:16 PM

vue3+vite:src は、イメージとエラー レポートと解決策を動的にインポートするために require を使用します。vue3+vite は複数のイメージを動的にインポートします。vue3。TypeScript 開発を使用している場合、イメージを導入するために require のエラー メッセージが表示されます。requireisnotdefined は使用できません。 vue2 のような imgUrl:require(' .../assets/test.png') は、typescript が require をサポートしていないため、インポートされます。そのため、import が使用されます。解決方法は次のとおりです: awaitimport を使用します

Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 May 20, 2023 pm 04:16 PM

Vue はブログ フロントエンドを実装しており、マークダウン解析を実装する必要があり、コードがある場合はコードのハイライトを実装する必要があります。 Vue には、markdown-it、vue-markdown-loader、marked、vue-markdown など、マークダウン解析ライブラリが多数あります。これらのライブラリはすべて非常に似ています。ここではMarkedが使用され、コード強調表示ライブラリとしてhighlight.jsが使用されます。 1. 依存ライブラリをインストールする vue プロジェクトの下でコマンド ウィンドウを開き、次のコマンド npminstallmarked-save//marked を入力して、マークダウンを htmlnpmins に変換します。

Vue3 でアバターを選択してトリミングする方法 Vue3 でアバターを選択してトリミングする方法 May 29, 2023 am 10:22 AM

最終的な効果は、VueCropper コンポーネントのyarnaddvue-cropper@next をインストールすることです。上記のインストール値は Vue3 用です。Vue2 の場合、または他の方法を参照したい場合は、公式 npm アドレス: 公式チュートリアルにアクセスしてください。また、コンポーネント内で参照して使用するのも非常に簡単です。必要なのは、対応するコンポーネントとそのスタイル ファイルを導入することだけです。ここではグローバルに参照しませんが、import{userInfoByRequest}from'../js/api を導入するだけです。 ' コンポーネント ファイルにインポートします。import{VueCropper}from'vue-cropper&

Vue3 の再利用可能なコンポーネントの使用方法 Vue3 の再利用可能なコンポーネントの使用方法 May 20, 2023 pm 07:25 PM

はじめに vue であれ、react であれ、複数の繰り返しコードに遭遇した場合、ファイルを冗長なコードの束で埋めるのではなく、これらのコードを再利用する方法を考えます。実際、vue と React はどちらもコンポーネントを抽出することで再利用を実現できますが、小さなコードの断片に遭遇し、別のファイルを抽出したくない場合は、それに比べて、React は同じファイル内で対応するウィジェットを宣言して使用できます。または、次のような renderfunction を通じて実装します。 constDemo:FC=({msg})=>{returndemomsgis{msg}}constApp:FC=()=>{return(

vue3+ts+axios+pinia を使用して無意味なリフレッシュを実現する方法 vue3+ts+axios+pinia を使用して無意味なリフレッシュを実現する方法 May 25, 2023 pm 03:37 PM

vue3+ts+axios+pinia で無意味なリフレッシュを実現 1. まず、プロジェクト内の aiXos と pinianpmipinia をダウンロードします--savenpminstallaxios--save2. axios リクエストをカプセル化-----ダウンロード js-cookienpmiJS-cookie-s// aixosimporttype{AxiosRequestConfig , AxiosResponse}from"axios";importaxiosfrom'axios';import{ElMess

vue3 プロジェクトをパッケージ化してサーバーに公開した後、アクセス ページが空白で表示される問題の解決方法 vue3 プロジェクトをパッケージ化してサーバーに公開した後、アクセス ページが空白で表示される問題の解決方法 May 17, 2023 am 08:19 AM

vue3 プロジェクトがパッケージ化され、サーバーに公開されると、アクセス ページに空白の 1 が表示されます。vue.config.js ファイル内の publicPath は次のように処理されます: const{defineConfig}=require('@vue/cli-service') module.exports=defineConfig({publicPath :process.env.NODE_ENV==='production'?'./':'/&

See all articles