ホームページ > ウェブフロントエンド > フロントエンドQ&A > Vueでデータを初期化する方法は何ですか?

Vueでデータを初期化する方法は何ですか?

青灯夜游
リリース: 2022-12-26 18:09:35
オリジナル
3791 人が閲覧しました

Vue がデータを初期化するには 2 つの方法があります: 1. オブジェクト モード、構文 "var data = {key-valueペア}"; 2. 関数モード、構文 "data: function () {return { key -値のペア}" }"。コンポーネントおよび拡張でのデータの初期化はオブジェクトにすることができないことに注意してください。そうでない場合は、エラーが報告されます。コンポーネント内のデータに関数モードを使用する目的は、複数のコンポーネント インスタンス オブジェクトが同じデータを共有してデータ汚染を引き起こすことを防ぐことです。

Vueでデータを初期化する方法は何ですか?

#このチュートリアルの動作環境: Windows7 システム、vue3 バージョン、DELL G3 コンピューター。

Vue データには関数とオブジェクトという 2 つの初期化メソッドがありますが、これら 2 つの状況に適用できるシナリオは何でしょうか?それは普遍的なものでしょうか?これら 2 つの質問を一緒に分析してみましょう

データ初期化

// 代码来源于官网示例

// 第一种定义方式
var data = { a: 1 }

// 直接创建一个实例
var vm = new Vue({
  data: data
})

// Vue.extend() 中 data 必须是函数
var Component = Vue.extend({
// 第二种定义方式
  data: function () {
    return { a: 1 }
  }
})
ログイン後にコピー
上記のコードは、データを定義する 2 つの方法を簡単に説明しています

  • function

  • object

公式 Web サイトのデモでは、オブジェクトがデータの初期化に使用できないことも強調されています。伸ばす。 。なぜ?

ソースコード解析

公式サイトのデモによると、Vue.extendのデータ初期化はオブジェクト化できないようです。強制的にオブジェクトとして書き込まれますか?

var Component = Vue.extend({
  data: { a: 1 }
})
ログイン後にコピー

実行後、Chrome のコンソールはエラーを直接報告します。情報は次のとおりです。

vue.esm.js?efeb:591 [Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.
ログイン後にコピー

ソース コードとエラー情報を分析することで、Vue.extend がトリガーされるとマージが実行されます基本コンポーネント (vmode 内、トランジションなど) を操作してマージし、extend で定義した情報は、mergeField を介してオプションにマージされます。データにマージされると、データが関数であるかどうかをチェックする strats.data がトリガーされます。ここではこれが必要です。フィルタ、コンポーネントなど、およびデータは 2 セットのマージ プロセスを通過することに注意してください。詳細については、次のコード コメントを参照してください。

// vue.extend 源码地址https://github.com/vuejs/vue/blob/dev/src/core/global-api/extend.js

  Vue.extend = function (extendOptions: Object): Function {
  ...
  // 在这里会触发mergeOptions方法
  Sub.options = mergeOptions(
      Super.options,
      extendOptions
    )
  ...
}

// mergeOptions 源码地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.js

export function mergeOptions (
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  ...

  const options = {}
  let key
  // parent对象内包含components、filter,、directive
  for (key in parent) {
    mergeField(key)
  }
  // child对象内对应的是Vue.extend内定义的参数
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  function mergeField (key) {
  // 这一步是根据传入的key找到不同的合并策略filter、components、directives用到合并策略是这个方法mergeAssets和data用到的不一样,当合并到data的时候会进入专属的合并策略方法内
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
}

// strats.data  源码地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.js
strats.data = function (
  parentVal,
  childVal,
  vm
) {
  if (!vm) {
  // 如果data不是function的话会直接走下面的报错信息
    if (childVal && typeof childVal !== 'function') {
      process.env.NODE_ENV !== 'production' && warn(
        'The "data" option should be a function ' +
        'that returns a per-instance value in component ' +
        'definitions.',
        vm
      );

      return parentVal
    }
    return mergeDataOrFn(parentVal, childVal)
  }

  return mergeDataOrFn(parentVal, childVal, vm)
};
ログイン後にコピー

その他の状況

実際、上記のコードは単なる単純なプロセスです。実際の開発では、次のような同様の状況が発生します。サブコンポーネントとルートはすべて mergeOptions メソッドを呼び出すため、データをオブジェクトとして定義できません。一番下

いつオブジェクトとして定義できるか

vueが初期化されるとき、次のように

new Vue({
  data: {
    linke: '//sinker.club'
  }
})
ログイン後にコピー

意味

さて、上で多くのことを述べてきましたが、これを行うことにどのような意味があるのでしょうか?なぜこれらの状況をオブジェクトとして定義できないのでしょうか? 実際、この質問に答えるには、js 自体に戻る必要があります。ご存知のように、js のデータ型は参照型と基本型に分けられます。参照型には、オブジェクト、配列、関数が含まれます。参照型とは何かは説明されません。ここで説明されています。

  var obj = {link: '//www.sinker.club'}
  var obj2 = obj
  var obj3 = obj
  obj2.link = "//gitlab.sinker.club"
  console.log(obj3.link) // "//gitlab.sinker.club"
ログイン後にコピー

上記のコードは、obj3 と obj2 の両方がメモリ内のアドレスを指しているため、obj2 の変更が obj3 に影響を与えるという問題が 1 つあります。もちろん、ディープ コピーを使用してこれに対処できます。問題。

  • JSON .parse(JSON.stringify(obj))

  • deepClone(obj)

しかし、これら 2 つの方法は毎回開発またはフレームワークが必要ですディープ コピーが必要ですデータ量が多いとパフォーマンスに良くありません。では、Vue はどのように行うのでしょうか?データを関数として定義する

function data() {
  return {
   link: '//sinker.club'
  }
}

var obj = test()
var obj2 = test()

obj2.link ="//gitlab.sinker.club"
console.log(obj.link) '//sinker.club'
ログイン後にコピー

なぜこれを行うのですか?解決シナリオは何ですか?

たとえば、サブコンポーネントを定義すると、データはオブジェクトとして定義されます。このコンポーネントは複数の場所で参照されます。このコンポーネントを参照しているデータの 1 つが変更されると、そのデータも変更されます。このコンポーネントを参照する他のデータも同時に変更されます。

#拡張知識:vue インスタンスを定義するときは、データ属性は次のいずれかです。 オブジェクトは関数にすることもできます。

const app = new Vue({
    el:"#app",
    // 对象格式
    data:{
        foo:"foo"
    },
    // 函数格式
    data(){
        return {
             foo:"foo"
        }
    }
})
ログイン後にコピー

コンポーネントで定義されるデータ属性は関数のみにすることができます。

コンポーネント データがオブジェクトとして直接定義されている場合

Vue.component('component1',{
    template:`<div>组件</div>`,
    data:{
        foo:"foo"
    }})
ログイン後にコピー

警告メッセージ

Vueでデータを初期化する方法は何ですか?

説明:

    vue 内のコンポーネントは次のとおりです。データを再利用しないためには、関数として定義します。
  • vue コンポーネント内のデータは互いに分離され、相互に影響を及ぼさないようにする必要があります。コンポーネントを再利用するたびに、データ データを 1 回コピーする必要があります。ある場所を再利用する 使用しているローカルコンポーネントのデータデータが変更されても、他の再利用ローカルコンポーネントのデータデータには影響しないため、data関数を通じてコン​​ポーネントの状態としてオブジェクトを返す必要があります。
  • コンポーネント内のデータを関数として記述すると、データは関数の戻り値の形式で定義されるため、コンポーネントが再利用されるたびに新しいデータが生成されます。独自のスコープを持つ返されることは、コンポーネント インスタンスごとにプライベート データ スペースを作成することに似ており、各コンポーネント インスタンスが独自のデータを維持できるようになります。
  • コンポーネントの日付を単純にオブジェクト形式で記述すると、これらのインスタンスは同じコンストラクターを使用しますが、JavaScriptの特性上、すべてのコンポーネントインスタンスは1つのデータを共有するため、すべてを変える結果に。

[関連する推奨事項: vuejs ビデオ チュートリアルWeb フロントエンド開発]

以上がVueでデータを初期化する方法は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート