ビュー 3 (1)
1. Vue3 の概要
2020 年 9 月 18 日、Vue.js バージョン 3.0、コードネーム: One Piece (ワンピース) がリリースされました。
2 年以上かかり、2,600 件以上の提出、30 件以上の RFC、600 件以上の PR、および 99 人の寄稿者が集まりました。
Vue3 がもたらすもの:
1. パフォーマンスの向上
- パックサイズが 42% 削減
- 初期レンダリング ブロック 55%、更新されたレンダリング ブロック 133%
- メモリが 54% 削減されました
2. ソースコードのアップグレード
- 応答性を実装するには、defineProperty の代わりに Proxy を使用します。
- 仮想 DOM と Tree-Sgaking の実装を書き直す
3. TypeScript を採用する
- Vue3 は TypeScript をより適切にサポートできるようになります
4. 新機能
(1)合成API(合成API)
- セットアップ構成
- リファレンスとリアクティブ
- 時計と時計効果
- 提供して注入する
(2) 新しい内蔵コンポーネント
- 断片
- テレポート
- サスペンス
(3) その他の変更点
- 新しいライフサイクルフック
- データオプションは常に関数として宣言する必要があります
- v-on の修飾子としてのkeyCodeサポートを削除
2.Vue3.0プロジェクトの作成
1.vue-cliを使用して作成する
公式ドキュメント: https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
// 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
// 安装或者升级你的@vue/cli
npm install -g @vue/cli
// 创建
vue create vue_test
// 启动
cd vue_test
npm run serve
2. viteを使って作成する
公式ドキュメント:https://v3.cn.vuejs.org/guide/installation.html#vite
vite公式ウェブサイト:https://vitejs.cn
-
ビタミンとは何ですか?——新世代のフロントエンド構築ツール
-
利点は次のとおりです。
1. 開発環境ではパッケージング作業が不要で素早いコールドスタートが可能
2. 軽量で高速なホットリロード (HMR)
3. アプリケーション全体がコンパイルされるのを待つ必要のない、真のオンデマンド コンパイル。
// 创建工程
npm init vite-app <project-name>
// 进入工程目录
cd <project-name>
// 安装依赖
npm install
// 运行
npm run dev
3. よく使われる複合API(複合API)
1. 開始するセットアップ
従来、vue2では複数の設定項目を組み合わせる方式(オプションAPI:データ、メソッドなど)でしたが、vue3では新たなメソッドであるComposition API(結合API)に変更され、セットアップはこれは API パフォーマンスの段階であり、コンポーネント内のすべてのデータとメソッドは setup 関数に記述されます。
このセットアップ関数には実際には 2 つの戻り値があります。
-
オブジェクトを返す
-
レンダリング関数を返します
最も一般的に使用される方法は、オブジェクトを返し、テンプレートでの使用を容易にするために使用されるすべてのプロパティとメソッドを返すことです (もちろん、後で説明するセットアップ構文シュガーがあります)。
<template>
<h1>个人信息</h1>
<h2>姓名:{
{ name }}</h2>
<h2>年龄:{
{ age }}</h2>
<button @click="sayHello">打招呼</button>
</template>
<script>
import {
h } from "vue";
export default {
name: "App",
// 此处只是测试一下setup,暂时不考虑响应式的问题
setup() {
// 数据
let name = "potato";
let age = 18;
// 方法
function sayHello() {
alert(`我叫${
name},我${
age}岁了`);
}
// 返回一个对象
return {
name,
age,
sayHello,
};
// 返回一个渲染函数
// return () => {return h('h1','哈哈哈哈')};
},
};
</script>
注: vue2 の属性メソッドはセットアップでアクセスできないため (ただし、 2 は 3 にアクセスできます) 、セットアップと vue2 のオプションの API を混合しないでください。これらが混合されている場合は、同じ名前のセットアップが優先されます。
また、戻り値はプロパティやメソッドではなく、Promise になるため、セットアップ前に async を追加しないでください。
2. 参照関数
vue2 の ref 属性を覚えていますか? vue2 の ref は id と似ています。Vue2 の ref 属性を確認する
Vue3のrefは関数です。
機能: 応答性の高いデータを定義します。
例: ボタンをクリックして情報を変更します
<template>
<h1>个人信息</h1>
<h2>姓名:{
{ name }}</h2>
<h2>年龄:{
{ age }}</h2>
<button @click="changeInfo">修改信息</button>
</template>
<script>
import {
ref } from "vue";
export default {
name: "App",
setup() {
// 数据
let name = ref("potato");
let age = ref(18);
// 方法
function changeInfo() {
// 直接这样写的话是不行的,因为ref把数据包装成了对象,对其操作时要加上‘.value’
// name= "李四";
// age= 13;
// console.log(name, age);
name.value = "李四";
age.value = 13;
}
// 返回一个对象
return {
name,
age,
changeInfo,
};
},
};
</script>
const xxx = ref(initValue)
応答データを含む参照オブジェクト ( RefImp オブジェクト)を作成しました
。js でデータを操作します。count.value
テンプレート内のデータを読み取ります。<div> {
{count}} </div>
(ここで value 属性が自動的に読み取られます)
実際、ref が受け入れることができるデータは基本的なデータ型だけでなく、複雑なデータ型も含まれますが、それはさらに面倒で、.value
<template>
<h1>个人信息</h1>
<h3>职业:{
{ job.type }}</h3>
<h3>工作地点:{
{ job.address }}</h3>
<button @click="changeInfo">修改信息</button>
</template>
<script>
import {
ref } from "vue";
export default {
name: "App",
setup() {
// 数据
let job = ref({
type: "前端工程师",
address: "广州",
});
// 方法
function changeInfo() {
;
job.value.type = "后端工程师";
job.value.address = "深圳";
}
// 返回一个对象
return {
job,
changeInfo,
};
},
};
</script>
基本データ型とオブジェクト データ型は、異なる方法で応答性を実装します。前者は依然として同じですObject.defineProperty()的get与set
が、後者は内部のreactive
関数に依存します。
3. リアクティブ機能
機能:オブジェクト型の応答型データを定義します(基本型には reactive を使用せず、ref を使用します)
<script>
import {
ref, reactive } from "vue";
export default {
name: "App",
setup() {
// 数据
let job = reactive({
type: "前端工程师",
address: "广州",
});
// 数组也可以
let hobby = reactive(["吃饭", "睡觉", "打豆豆"]);
// 方法
function changeInfo() {
job.type = "后端工程师";
job.address = "深圳";
hobby[2] = "学习";
}
// 返回一个对象
return {
job,
changeInfo,
hobby,
};
},
};
</script>
const 代理对象 = reactive(源对象)
オブジェクトまたは配列を受け取り、プロキシ オブジェクトを返します (Proxy オブジェクト)
- reactiveで定義されるレスポンシブデータは「深い」
- 内部プロキシ実装は ES6 に基づいており、ソース オブジェクトの内部データはプロキシ オブジェクトを通じて操作されます。
ここで注意すべき点は、応答性はジョブ内の特定の属性を変更することによってのみ実現できることです。ジョブを直接変更すると、ジョブが読み取り専用であることを示す警告がレポートされます。ジョブを変更したい場合は、Object.assign(job, newObj); または job= { …job, …newProperties }; が必要です。
4. Vue3 の応答原理
(1) Vue2のレスポンシブ原則
Vue3 の応答性の原理を理解する前に、まず vue2 の応答性を確認してみましょう。
Object.defineProperty()
vue2 はオブジェクト型データをハイジャックし、gette
r と を追加することでデータを監視していることがわかりますsetter
。配列の場合、配列を更新するメソッドはオーバーライドされます。vue2 監視データの原則を確認する
vue2 監視データには 2 つの問題があります。
- 属性を直接追加または削除した場合、インターフェイスは更新されません。
- 添字を使用して配列を直接変更した場合、インターフェイスは自動的に更新されません。
$set
これら 2 つの問題は、 、 、 によって解決できます$delete
。splice(数组变更方法)
(2) Vue3のプロキシ
vue3 では、vue2 の 2 つの問題が解決されています。
<button @click="addSex">添加一个sex属性</button>
<button @click="deleteName">删除一个name属性</button>
function addSex() {
// 如果是vue2,要这样写this.$set(this.person, 'sex', '女');
person.sex = "女";
}
function deleteName() {
// 如果是vue2,要这样写this.$delete(this.person, 'name');
delete person.name;
}
以下は、vue3 で応答性をシミュレートする原理です。
<script>
let person = {
name: "potato",
age: 18,
};
// 模拟Vue3实现响应式
const p = new Proxy(person, {
// 有人在读取p的某个属性时调用
get(target, propName) {
console.log(`有人读取了p身上的${
propName}属性`);
return target[propName];
},
// 有人在修改p的某个属性、或给p追加某个属性时调用
set(target, propName, value) {
console.log(`有人修改了p身上的${
propName}属性,我要去更新界面了`);
target[propName] = value;
},
// 有人在删除p的某个属性时调用
deleteProperty(target, propName) {
console.log(`有人删除了p身上的${
propName}属性,我要去更新界面了`);
return delete target[propName];
},
});
</script>
これはより厳密であり、追加、削除、変更、チェックReflect(反射)
に使用されます。これはフレームワークのアプローチでもあります。実際、本質的には大きな違いはありません。ただReflect
、エラーをより適切に捕捉し、一部のエラー レポートを回避できるというだけです。それは捕らえtry-catch
られなければならない。ここであまり複雑に考えないでください。実際にはフレームワークをより使いやすくするためです (エラー報告が少なくなります)。
Proxy(代理)
+Reflect(反射)
<script>
let person = {
name: "potato",
age: 18,
};
// 模拟Vue3实现响应式
const p = new Proxy(person, {
// 有人在读取p的某个属性时调用
get(target, propName) {
console.log(`有人读取了p身上的${
propName}属性`);
return Reflect.get(target, propName);
},
// 有人在修改p的某个属性、或给p追加某个属性时调用
set(target, propName, value) {
console.log(`有人修改了p身上的${
propName}属性,我要去更新界面了`);
Reflate.set(target, propName, value);
},
// 有人在删除p的某个属性时调用
deleteProperty(target, propName) {
console.log(`有人删除了p身上的${
propName}属性,我要去更新界面了`);
return Reflate.deleteProperty(target, propName);
},
});
</script>
(3) Vue3 の応答原理のまとめ ⭐
ref
と ではreactive
異なります
単純な型の ref が渡されます: Object.defineProperty() の get および set . もちろん、 ref で定義された複合型も渡されます: reactive の Proxy
Reactive は、Proxy (前述)を通じて応答性を実装し、Reflect を通じてソース データを操作します。
とにかく、要約すると、vue3 の新しい点は、複雑なデータ型に対して Proxy を介した応答性を実装することです。つまり、次の 2 点です。
- プロキシ経由: 属性の追加と削除、属性値の読み取りと書き込みなど、オブジェクト内の属性の変更をインターセプトします。
- Reflect 経由: ソース オブジェクトのプロパティに対して上記の操作を実行します。
new Proxy(person, {
// 拦截读取属性值
get(target, propName) {
return Reflect.get(target, propName);
},
// 拦截设置属性值或添加属性值
set(target, propName, value) {
Reflate.set(target, propName, value);
},
// 拦截删除属性
deleteProperty(target, propName) {
return Reflate.deleteProperty(target, propName);
},
});
5. リアクティブとリファレンスの比較
(1) さまざまなデータ カテゴリを定義する
ref
基本的な型データを定義するために使用されますreactive
オブジェクトまたは配列型のデータを定義するために使用されます- 注:オブジェクトまたは配列タイプの data
ref
を定義することもできます。これらは内部でプロキシ オブジェクトに自動的に変換されます。reactive
(2) 原理の違い
- ref はパススルーされます:
Object.defineProperty()
そしてもちろんget
、set
複合型はリアクティブ プロキシ経由で渡されます。 - reactive は、
Proxy
応答性 (前述) を実装し、Reflect
ソース データを操作するために使用されます。
(3) さまざまな使い方
ref
定義したデータは、を操作する場合には .value が必要ですが、テンプレートの読み込みには .value は必要ありません。reactive
定義されたデータ、操作、読み取りには.value は必要ありません。
6. セットアップ時の2つの注意点
(1) 実行タイミング
setup
関数の実行時間はbeforeCreate之前
、つまりすべてのライフ サイクルの先頭にあります。現時点では、これは未定義です。つまり、セットアップでこれを介してコンポーネント インスタンスにアクセスすることはできません。
ここでの beforeCreate はsetup の外側に書かれていることに注意してください。 setup の内側にある場合、 setup の実行タイミングはこれら 2 つのフックと同等であるため、 beforeCreate フックと created フックは存在しません ( setup はすべてのフックより前に実行されるため、必要なコードを書くだけです)これら 2 つのフックをステップの前に書きたい)
(2)設定パラメータ
setup は 2 つのパラメータを受け取ります。(props,context)
props
これは、コンポーネントの外部から渡され、コンポーネント内の宣言によって受け取られる属性を含むオブジェクトです。context
は 3 つの属性を含むオブジェクトです。attrs、slots、emit
- 最初のものは、値がコンポーネントの外部から渡されるが、構成内で宣言されていないオブジェクトと
attrs
同等です。this.$attrs
props
- 2 番目の
slots
同等の にthis.$slots
は、受信したスロットの内容が含まれます。 - 3 番目のイベントは、コンポーネントをトリガーするために使用されるカスタム イベント
emit
に相当します。this.$emit
props: ['name', 'age']
setup(props, context) {
console.log(props) // Proxy{name:'potato',age:18}:组件外部传递过来,且组件内部声明接收了的属性。
console.log(context.attrs)//相当于this.$attrs
console.log(context.slots)相当于this.$slots
console.log(context.emit)//相当于this.$emit
}
4. 演算機能と監視機能
1. 計算関数(計算済み)
機能はvue2と同じですが、関数となるため手動で導入する必要があります。デフォルトの記述方法はコールバックを渡すことです
省略形のみを使用した場合、計算されたプロパティ値を変更すると、プロパティ値が読み取り専用であることを示す警告がコンソールに表示されます。
これは、計算されたプロパティはデフォルトでは読み取り専用であり、依存する値が変更されると自動的に変更されるためです。getter
計算された属性を変更する場合は、次の完全な書き込みメソッドを使用して、とを含むオブジェクトを渡します。setter
中央setter
のパラメーターは変更された新しい値です。
<template>
<h1>个人信息</h1>
姓:<input type="text" v-model="person.firstName" />
<br />
名:<input type="text" v-model="person.lastName" />
<br />
全名:<input type="text" v-model="person.fullName" />
<br />
<span>全名:{
{ person.fullName }}</span>
</template>
<script>
import {
computed, reactive } from "vue";
export default {
setup() {
let person = reactive({
firstName: "张",
lastName: "三",
});
// 计算属性-简写(没有考虑计算属性被修改的情况)
// person.fullName = computed(function () {
// return person.firstName + "-" + person.lastName;
// });
// 计算属性-完整(包括读和写)
person.fullName = computed({
get() {
return person.firstName + "-" + person.lastName;
},
set(value) {
const nameArr = value.split("-");
person.firstName = nameArr[0];
person.lastName = nameArr[1];
},
});
return {
person,
};
},
};
</script>
2. モニタリング機能(見守り)
実はvue3のwatchの機能はvue2と同じですが、書き方が異なります。
vue2 の listen 関数の書き方. vue2 の listen 関数のレビューはここをクリックしてください。
まずデータを準備しましょう。
import {
ref, reactive } from 'vue'
const sum = ref(0)
const msg = ref('hello')
const person = reactive({
name: 'potato'
age: 18
job: {
type: 'code'
salary: 10
}
})
(1) 第一パラメータの書き方
- シナリオ 1: vue3 は、ref によって定義された応答データを監視します
watch(sum, (newVal, oldVal) => {
console.log("sum的值变了", newVal, oldVal);
});
- シナリオ 2: vue3 は、ref で定義された複数の応答データを監視します
watch([sum, msg], (newVal, oldVal) => {
console.log("sum或msg变化了", newVal, oldVal);//new和old也是监听值构成的数组
});
- シナリオ 3: reactive で定義されたリアクティブ データを監視します。
ここには 2 つの落とし穴があります。1 つ目は、reactive
定義されたデータであり、監視中にコールバックで取得できませんoldValue
。oldValue は newValue と同じです
。2 番目の落とし穴は、reactive
定義されたデータの監視がデフォルトで有効になっておりdeep:true
、deep
変更できないことです。false
watch(person, (newVal, oldVal) => {
console.log("person变化了");
},{
immediate:true,deep:false});
- シナリオ 4: reactive で定義された reactive データ内の属性を監視します。ここで、最初のパラメーターはアロー関数として記述する必要がある
ことに注意してください。person.job を直接記述する場合、それは無効な値を書き込むことと同じです。モニター不可、到着しました。また、ジョブがオブジェクトである場合、デフォルトの deep は false です。詳細な監視が必要な場合は、手動で deep:true をオンにする必要があります(deep 構成は有効です)。
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{
immediate:true,deep:true})
- シナリオ 5: reactive で定義された応答データ内の一部の属性を監視する
この状況は上記と似ていますが、違いは、最初のパラメーターが配列として書き込まれ、各要素がアロー関数であり、返される new および old値も同様であり、対応する値の配列。
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{
immediate:true,deep:true})
(2) 第一引数に.valueを書くかどうか
person を ref 定義に置き換えるとどうなるでしょうか? ではモニタリング時に書くべきなのでしょうか.value
?
import {
ref, reactive } from 'vue'
const sum = ref(0)
const msg = ref('hello')
const person = ref({
name: 'dantin'
age: 18
job: {
type: 'code'
salary: 10
}
})
答えは「書き込み」です。ref
複雑なデータ型の場合、応答性は内部で実装されるため、このように記述することは、reactive
定義された応答性データProxy
を書き込むことと同じでありreactive
、監視中に対応する落とし穴もあります (上記の状況 3 を参照)。
watch(person.value,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{
immediate:true,deep:false}) //此处的deep配置不奏效
さらに、その人(一人ですRefImpl对象
)を徹底的に観察することで、価値観やより深い変化を監視する方法もあります。これは、人を読み込まずに直接監視すると.value
、オブジェクトが監視されるためRefImpl
です。値のアドレスが変化した場合のみ監視できます。値の変化は監視できないため、deep をオンにする必要があります。
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{
immediate:true,deep:true})
では、なぜ単純なデータ型が必要ないのでしょうか.value
? 実際には、上記のケース 4 と同じで、単純なデータ型が direct の場合.value
、監視されるのはハードコーディングされた値です。それ以外の場合.value
、監視されるのは応答性の高いRefImpl
オブジェクトであり、内部の値が変化したときに監視できます。
watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
})
必要に応じて.value
、アロー関数を使用して動的に読み取り、合計が変化するたびにコールバックが実行され、最新の値を読み取ります。
watch(() => sum.value,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
})
3.watchEffect関数
watch
ルーチンは、監視対象の属性と監視対象のコールバックの両方を指定することです。watchEffect
ルーチンは、どの属性を監視するかを指定する必要はなく、どの属性が監視コールバックで使用され、どの属性を監視するかということです。
watchEffect は computed に少し似ていますが、computed は計算値 (コールバック関数の戻り値) に焦点を当てているため、戻り値を記述する必要があります。WatchEffect は処理 (コールバック関数の関数本体) に注目するため、戻り値を記述する必要はありません。
//watchEffect的回调一上来会先执行一次
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(() => {
const x1 = sum.value;
const x2 = person.job.salary;
console.log("watchEffect所指定的回调执行了");
});