Web フロントエンド インタビュー高頻度テストサイト - Vue3.x (Composition API の論理的な再利用、応答性を実現するためのプロキシ)

シリーズ記事ディレクトリ

コンテンツ 参考リンク
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)

不积跬步无以至千里 不积小流无以成江海

クリックしてフォローし、迷子にならないように、更新を続けてください...

おすすめ

転載: blog.csdn.net/qq_45902692/article/details/126681278