シリーズ記事ディレクトリ
コンテンツ | 参考リンク |
---|---|
JavaScript面接高頻度テストサイト | HTML、CSS、JavaScript、ES6、AJAX、HTTP面接試験サイト |
Vue2.x インタビュー高頻度テストサイト | Vue2.x インタビュー高頻度テストサイト |
Vue3.x の新しい API | ref、toRef、および toRefs のライフサイクル、理解、および最適な使用 |
Vue3.x アップグレードの重要な機能 | エミット プロパティ、ライフ サイクル、複数のイベント、フラグメント、.async の削除、非同期コンポーネントの書き込み、フィルターの削除、テレポート、サスペンス… |
記事ディレクトリ
1. コンポジション API がロジックの再利用を実装する方法
- ロジック コードを関数に抽出する
- 関数の命名規則は useXxx 形式です (React Hooks も)
- セットアップでの useXxx 関数の参照
useMousePosition.js ファイル
- マウスの位置を示すマウス移動イベント
- 論理的な再利用のために js ファイルに記述
import {
ref, onMounted, onUnmounted} from 'vue'
function useMousePosition() {
// 初始化坐标
const x = ref(0)
const y = ref(0)
// 更新坐标
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
// 挂载:添加鼠标移动事件
onMounted(() => {
console.log('useMousePosition mounted');
window.addEventListener('mousemove', update)
})
// 销毁:删除鼠标移动事件
onUnmounted(() => {
console.log('useMousePosition unMounted');
window.removeEventListener('mousemove', update)
})
return {
x,
y
}
}
export default useMousePosition
App.vue 親コンポーネント
- ボタンをクリックして、コンポーネントを作成/破棄します
<template>
<MousePosition v-if="flag" />
<button @click="changeFlagHandler">change flag</button>
</template>
<script>
import MousePosition from "./components/index.vue";
export default {
data() {
return {
flag: true,
};
},
methods: {
// 实现组件的创建/销毁
changeFlagHandler() {
this.flag = !this.flag;
},
},
components: {
MousePosition },
};
</script>
index.vue 子コンポーネント
- 関数で定義された x と y を分解します
<template>
<p>mouse position {
{
x }} {
{
y }}</p>
</template>
<script>
import useMousePosition from "./useMousePosition";
export default {
name: "MousePosition",
setup() {
// 解构 x 和 y
const {
x, y } = useMousePosition();
return {
x,
y,
};
},
};
</script>
コンポジション API の再利用
2. Vue3 が応答性を実装する方法
1. Object.defineProperty の短所
- ディープ リスニングには 1 回の再帰が必要です (深いレベルはパフォーマンスに影響します)
- プロパティの追加/削除をリッスンできません (Vue.set Vue.delete)
- アレイをネイティブに監視できないため、特別な処理が必要です
2.プロキシは応答性を実装します
- target: 定義されたオブジェクト データです。
- key: 取得するキー
- val: 取得する値
- 受信者: はproxyDataです
例: オブジェクトはプロキシを介してリアクティブ テストを実装します
const data = {
name: '杂货铺',
age: 20
}
const proxyData = new Proxy(data, {
// 监听获取
get(target, key, receiver) {
const result = Reflect.get(target, key, receiver)
console.log('get', key);
return result // 返回结果
},
// 监听设置
set(target, key, val, receiver) {
const result = Reflect.set(target, key, val, receiver)
console.log('set', key, val)
console.log('result', result); // true
return result // 是否设置成功
},
// 监听删除
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
console.log('delete property', key);
console.log('result', result); // true
return result // 是否删除成功
}
})
例: Array は Proxy を介してリアクティブ テストを実装します
const data = ['a', 'b', 'c']
const proxyData = new Proxy(data, {
get(target, key, receiver) {
// 只处理本身(非原型的)属性
const ownKeys = Reflect.ownKeys(target) // 获取对象的键
if (ownKeys.includes(key)) {
console.log('get', key); // 监听
}
const result = Reflect.get(target, key, receiver)
console.log('get', key);
return result // 返回结果
},
set(target, key, val, receiver) {
// 重复的数据,不处理
const oldVal = target[key]
if(val === oldVal) {
return true
}
const result = Reflect.set(target, key, val, receiver)
console.log('set', key, val)
console.log('result', result); // true
return result // 是否设置成功
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
console.log('delete property', key);
console.log('result', result); // true
return result // 是否删除成功
}
})
3. リフレクト機能
- Proxy機能による1対1対応
- 正規化、標準化、機能的
- オブジェクトのユーティリティ関数を置き換える
4.プロキシは応答性を実装します
- 詳細な監視、パフォーマンスの向上 (必要に応じてリッスン)
- 新規/削除されたプロパティを監視できます
- アレイの変更を監視可能
- Proxy は Object.defineProperty の問題を回避できます
- プロキシはすべてのブラウザーと互換性があるわけではなく、ポリフィルできません (ブラウザーがネイティブ API をサポートしていないコードを実装するために使用されます)。
例: プロキシによるリアクティブ
- ディープ モニタリングは 1 回限りのモニタリングではなく、使用される場合のみです。
// 创建响应式
function reactive(target = {
}) {
if (typeof target !== 'object' || target == null) {
// 不是对象或数组
return target
}
// 代理配置
const proxyConf = {
get(target, key, receiver) {
// 只处理本身(非原型的)属性
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('get', key); // 监听
}
const result = Reflect.get(target, key, receiver)
// 深度监听
// 性能如何提升的? 什么时候 get 到,什么时候去做响应式
return reactive(result) // 返回结果
},
set(target, key, val, receiver) {
// 重复的数据,不处理
const oldVal = target[key]
if (val === oldVal) {
return true
}
// 监听是已有的键还是新增的键
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('已有的 key', key);
} else {
console.log('新增的 key', key);
}
const result = Reflect.set(target, key, val, receiver)
console.log('set', key, val)
return result // 是否设置成功
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
console.log('delete property', key);
console.log('result', result); // tru return result // 是否删除成功
}
}
// 生成代理对象
const observed = new Proxy(target, proxyConf)
return observed
}
// 测试数据
const data = {
name: '杂货铺',
age: 21,
info: {
city: 'beijing'
}
}
const proxyData = reactive(data)
不积跬步无以至千里 不积小流无以成江海
クリックしてフォローし、迷子にならないように、更新を続けてください...