背景: Vue のコンポーネント化はその特徴です。コンポーネントを定義することがよくありますが、コンポーネントのデータが関数として定義されていることはわかりますし、データ汚染を避けるためであることもわかりますが、ルート インスタンスは必須ではありません (ルート インスタンスはシングルトンです。データ汚染を心配する必要はありません)、具体的な理由は何ですか? ソース コードからも分析してみましょう。詳細については、ソース コード: src/core/instance/state.js の initData() メソッドを参照してください。もちろん、デモも使用して説明します。デモは次のとおりです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue data</title>
</head>
<body>
<div>vue组件data为什么必须是个函数而Vue的根实例则没有限制?源码中详见:src/core/instance/state.js中的initData()</div>
<div id="demo">
<div>vue组件data为什么必须是个函数?</div>
<comp></comp>
<comp></comp>
<div>{
{counter}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('comp',{
template:'<div @click="counter++">{
{counter}}</div>',
// data: {counter: 0}如果这么定义首先会报错,要求data为函数,原因是为了避免多个组件数据互相影响,造成数据污染,一会从源码中解释
data () {
return {
counter:1
}
}
})
//创建实例
const app = new Vue({
el: '#demo',
data:{counter:1}
});
console.log(app.$options.render);
</script>
</body>
</html>
1. ソース コードでコンポーネント データが関数でなければならないと説明している理由は次のとおりです。
上記のことから、コンポーネントがその機能を使用しない場合、データが共有され、データが汚染されることがわかります。
2. 先ほど、ルートコンポーネントのデータに制限がないと言ったのは、const app = new Vue({el:'#demo'}) がシングルトンであるためです。ソースコードは次のとおりです: /src/core/instance/init.js
mergeoptions にブレークポイントを追加すると、カスタム ビルドが最初に実行され、次にルート コンポーネントが実行されることがわかります。ソース コードの場所: /src/core/util/options.js。詳細については、マージを参照してください。戦略は次のようになります。
上記より、カスタムコンポーネント利用時にvmが存在しない場合に判定が行われることが分かりますが、ルートコンポーネントインスタンスが作成されている場合は条件検出が行われないため、ルートコンポーネント内のデータは取得されません。関数として定義する必要があります。
要約すると、次の結論が得られます。
Vue コンポーネントには複数のインスタンスが存在する可能性があり、データをオブジェクトの形式で直接定義すると、コンポーネントがデータ オブジェクトを共有することになり、状態の変更がすべてのコンポーネント インスタンスに影響するため、これは不合理です。関数の形式では、initData 時に新しいデータ オブジェクトを返すファクトリ関数として使用され、インスタンス間の状態汚染の問題を回避します。ただし、ルート インスタンスは 1 つだけであり、この問題について心配する必要はないため、vue ルート インスタンスの作成時にはこの制限は存在しません。
要約すると、vue のカスタム コンポーネントのデータを関数として定義する必要がある理由が説明されていますが、ルート インスタンスにはこの制限がないため、皆様のお役に立てれば幸いです。