Быстро освоить разработку сегментов семейства Vue3

внешний фреймворк

предисловие

Vue3Появление идеального решенияVue2Дефекты в некоторых аспектах, давайте пройдемся вместеVue3, посмотрите, какие изменения он нам приносит~

Vue3

Vue3СравниватьVue2Быстрее, меньше и меньше41%, улучшена скорость рендеринга33%, использование памяти падает54%. более гибкийComposition APIи идеальная поддержкаTypeScript. Благодаря этим цифрам и преимуществам нам очень важно поставитьVue3Удачной учебы! Ниже у нас естьVue3общий вCompsition APIОбъясните подробно.

Документация Vue3 на китайском языке

Composition API

Документация по составу API на китайском языке

  • setup

setupфункцияфункция входа, В этой функции мы можем определить переменные, функции, жизненные циклы и т. д., а затем экспортировать их, к которым можно получить доступ на странице. Конкретные этапы использования следующие:

<template>
    <p>数字为:{{num}}</p>
    <p>两倍为:{{double}}</p>
    <button @click="sum">累加</button>
</template>
<script>
import { ref, onMounted, computed } from "vue"; // 导入Vue3中的核心方法
export default {
    ..., // 可以定义一些Vue2时的options
    setup() {
        const num = ref(666); // 定义一个响应式的常量
        
        const sum = (a, b) => a + b; // 定义一个方法
        
        const double = computed(() => num.value+1) // 定义一个计算属性
        
        onMounted(() => {
            console.log('页面加载完执行的生命周期钩子函数')
        })
        
        // ...等等都可以定义在setup函数中
        
        return { // 导出定义的变量和方法,在模板中使用
            num,
            sum,
            double
        }
    }
}
</script>

Уведомление:setupФункция принимает два аргумента:props,context;

  1. propsПредставляет свойство, переданное из родительского компонента, и значение является адаптивным. Если значение изменить, страница будет обновлена. Следовательно,propsДеструктуризация невозможна, но вы можете использоватьtoRefsПроведите деструктуризацию, иначе он потеряет отзывчивость.
  2. contextконтекст, содержащийattrs,slots,emitЖдать. Он не реактивный, поэтому его можно разобрать

когдаsetupПри выполнении экземпляр компонента не создается и может получить доступ только к следующим свойствам:props,attrs,slots,emit. Нет доступа к другим параметрам:computed,methodsЖдать.

Далее мы подробно объяснимVue3Общие основные методы в !

  • ref

ref: обычно задайте значение базового типа данных для адаптивного значения.

<template>
    <p v-show="flag">是否显示</p>
    <p>我的名字:{{name}}</p>
    <p>我的年龄:{{age}}</p>
    <p ref="refDom">你好啊</p>
</template>
<script>
import { ref } from "vue";
export default {
    setup() {
        const flag   = ref(false); // 定义 Boolean 类型的变量
        const age    = ref(25);    // 定义 Number 类型的变量
        const name   = ref('tmc'); // 定义 String 类型的变量
        const refDom = ref(null);  // 可以访问到 Dom 元素
        
        return {
            flag,
            age,
            name,
            refDom
        }
    }
}
</script>

Уведомление:refОпределенные переменные будут автоматически расширены в шаблоне, поэтому нет необходимости использовать.value;существуетsetupИспользование этих переменных в функции не требует добавления.value

  • reactive

Реактивное: обычно устанавливает значение типа ссылочного типа на адаптивное значение

<template>
    <p>我的名字:{{state.name}}</p>
    <p>我的年龄:{{state.age}}</p>
</template>
<script>
import { reactive } from "vue";
export default {
    setup() {
        const state = reactive({
            name: 'tmc',
            age: 25
        })
        
        return {
            state
        }
    }
}
</script>

Уведомление:

  1. reactiveпохожий наVue2серединаVue.observable()
  2. Если вы хотите легко использовать его в модуле, вы можете использоватьtoRefsэкспорт
  3. ref(variable)Эквивалентноreactive({value: variable})
  • toRefs

toRefs: преобразует реактивные объекты в обычные объекты.

<template>
    <p>我的名字:{{name}}</p>
    <p>我的年龄:{{age}}</p>
</template>
<script>
import { toRefs, reactive } from "vue";
export default {
    setup() {
        const data = reactive({
            name: 'tmc',
            age: 25
        })
        
        return {
            ...toRefs(data)
        }
    }
}
</script>

Уведомление:toRefsПреобразуйте оба свойства вref; поэтому он не теряет своей отзывчивости при деструктурировании

  • toRaw

toRaw: возвращеноreactiveилиreadonlyметоды конвертируются в простые объекты для реактивных прокси

<template>
    <!-- ... -->
</template>
<script>
import { toRaw, reactive, ref } from "vue";
export default {
    setup() {
        const data1 = reactive({
            name: 'tmc',
            age: 25
        })
        const data2 = ref(666)
        
        const changeData1 = toRaw(data1)
        const changeData2 = toRaw(data2.value)
        
        return {
            ...toRefs(data)
        }
    }
}
</script>

Уведомление: при конвертацииrefобъект, вам нужно пройти.value

  • provide & inject

обеспечить и ввести: родительский компонент предоставляет данные с помощью параметра предоставления, а дочерний компонент принимает и использует предоставленные данные с помощью параметра ввода

<!-- 父组件 -->
<template>
    <my-test></my-test>
</template>
<script>
import { provide } from "vue";
import MyTest from './MyTest';
export default {
    components: {
        MyTest
    },
    setup() {
        provide('name', 'tmc')
        // 可提供多个 provide
        return {
            // ...
        }
    }
}
</script>

Уведомление:provideПринимает два параметра, первыйkey, другойvalue

<!-- 子组件 -->
<template>
    <p> {{name}} </p>
</template>
<script>
import { inject } from "vue";
export default {
    components: {
        MyTest
    },
    setup() {
        const name = inject('name');
        // inject('name', 'xxx'); // 可指定默认值
        return {
            name
        }
    }
}
</script>

Уведомление:injectПервый параметрkey, второй параметр может указывать значение по умолчанию (необязательно)

Чтобы предоставить и ввести реактивные значения, вы можете предоставитьprovideиспользовать, когдаrefа такжеreactive

  • computed

вычислено: для вычисления свойств, пожалуйста, обратитесь к приведенному выше примеру.

  • watch & watchEffect

Использование: смотреть( источник, cb, [опции] )

  1. watchмониторrefСозданы адаптивные данные

    <template>
        <!-- ... -->
    </template>
    <script>
    import { watch, ref } from "vue";
    export default {
        setup() {
            const name = ref('tmc');
            
            watch(name, (newVal, oldVal) => {
                console.log('新值:' + newVal)
                console.log('旧值:' + oldVal)
            })
            
        }
    }
    </script>
    
  2. watchмониторreactiveСозданы адаптивные данные

    <template>
        <!-- ... -->
    </template>
    <script>
    import { watch, reactive } from "vue";
    export default {
        setup() {
            const data = reactive({
                name: 'tmc',
                age: 25
            });
            
            // 监听单个属性
            watch(() => data.name, (newVal, oldVal) => {
                console.log('新值:' + newVal)
                console.log('旧值:' + oldVal)
            })
            
            // 监听多个属性
            watch(() => [data.name, data.age], ([newName, oldName], [newAge, oldAge]) => {
                console.log('新值:' + newName)
                console.log('旧值:' + oldName)
                console.log('新值:' + newAge)
                console.log('旧值:' + oldAge)
            })
            
        }
    }
    </script>
    

watch,watchEffectвернет функцию, чтобы остановить слушателяstop, пользователь может остановить мониторинг.

Уведомление:watchа такжеwatchEffectразница?

  1. watchэто свойство, которое необходимо передать для мониторинга, иwatchEffectзаключается в автоматическом сборе зависимостей
  2. watchВы можете увидеть изменение значения свойства до и после, а такжеwatchEffectнет
  3. watchвыполняется при изменении свойства, иwatchEffectПо умолчанию он будет выполнен один раз, и изменения свойств также будут выполнены.
  • ...

БолееComposition APIИнформацию об использовании и мерах предосторожности см.API композиции Vue

Жизненный цикл

Основное использование каждого жизненного цикла:

<template>
    <!-- ... -->
</template>
<script>
import { onMounted, onUpdated, onUnmounted } from "vue";
export default {
    setup() {
        onMounted(() => {
          console.log('mounted!')   // 挂载
        })
        onUpdated(() => {
          console.log('updated!')   // 更新
        })
        onUnmounted(() => {
          console.log('unmounted!') // 销毁
        })
    }
}
</script>

с версией 2.хразница

  • beforeCreate-> использоватьsetup
  • created-> использоватьsetup
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

Добавлена ​​функция хука:

  • onRenderTracked
  • onRenderTriggered

Пользовательские функциональные хуки

Опустите, чтобы загрузить больше

// hooks/useLoadMore.ts
import { computed, onMounted, Ref } from 'vue';
import { IGlobalState } from '@/store';
import { Vuex } from 'vuex';
import _ from 'lodash';

export function useLoadMore(refreshEle: Ref<null | HTMLElement>, store: Store<IGlobalState>, type: string) {
    let element: HTMLElement; // 需要滚动的元素
    
    function _loadMore() {
        let containerHeight = element.clientHeight; // 获取可视区域的高度
        let scrollTop = element.scrollTop; // 获取滚动的高度
        let scrollHeight = element.scrollHeight; // 获取这个列表的高度
        
        if(containerHeight + scrollTop + 25 >= scrollHeight) {
            store.dispatch(type); // 派发action
        }
    }
    
    onMounted(() => {
        element = refreshEle.value as HTMLElement;
        
        element.addEventListener('scroll', _.debounce(_loadMore, 200)); // 防抖
    })
    
    // 可更改loading、hasMore等状态
    const isLoading = computed(() => {
        return store.state.home.homeList.loading
    })
    const hasMore = computed(() => {
        return store.state.home.homeList.hasMore
    })
}

использовать на странице

// index.vue
<template>
	...
    <div ref="refreshEle">
        ...
        <HomeList :xxx="xxx"></HomeList>
        ...
    </div>
    ...
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { Store, useStore } from 'vuex';
import { IGlobalState } from '@/store';
import { useLoadMore } from '@/hooks/useLoadMore';
export default defineComponent({
    ...
    setup() {
    	let store = useStore<IGlobalState>();
   		let refreshEle = ref<null | HTMLElement>(null);
    	const { isLoading, hasMore } = useLoadMore(refreshEle, store, `home/${types.SET_HOME_LIST}`);
    
    	return {
            refreshEle,
            isLoading,
            hasMore
        }
	}
    ...
})
</script>

Встроенные компоненты

Набор для телепортации

  • TeleportМодули можно перемещать в текущийDOMТехники в других местах вне Элементов
// index.html
<html>
    ...
    <div id="app"></div>
    <div id="teleport-toast"></div>
</html>


// components/index.vue
<button @click="showToast">显示toast</button>
<teleport to="#teleport-toast">
    <div v-show="showFlag">
        <div>
            显示 Toast 内容
        </div>
    </div>
</teleport>
import { defineComponent, ref } from 'vue';
export default defineComponent({
	setup() {
        const showFlag = ref(false);
        const showToast = (() => {
        	showFlag.value = true;    
        });
        
        return {
            showFlag,
            showToast
        }
    }  
})

Суммировать:использоватьteleportкомпоненты, черезtoсвойств, вручную укажите место, где компонент отображается и<div id="app"></div>тот же уровень, ноteleportположение делshowFlagопять же полностью изнутриVueУправление компонентами, это очень приятно~!

Suspense загружает компоненты асинхронно

<Suspense>
    <!-- #default可不写 -->
	<template #default>
    	<xxxx>某某组件</xxxx>
    </template>
    <template #fallback>
    	<div>Loading...</div>
    </template>
</Suspense>

Уведомление:#default,#fallbackявляется сокращением для использования именованных слотов, например:v-slot:tmc === #tmc

расширять:Reactтакже содержит<Suspense>компоненты, часто сReact.lazy()Используется в сочетании

// 基本用法
import React, { Suspense } from 'react';

const Page = React.lazy(() => import('./Page'));

<Suspense fallback={<div> Loading... </div>}>
	<Page />
</Suspense>

Vue3серединаdefineAsyncComponentа такжеReact.lazy()аналогичный

Fragement

существуетVue2.x, компонент может иметь только один кореньDOM,существуетVue3, компонент может иметь несколько корнейDOM

Глобальный API

  • getCurrentInstance
  • Изменения в способе регистрации компонентов
// Vue2 使用 Vue.component 方法
import Vue from 'vue';
import Test from './Test.vue';

Vue.component('Test', Test);

// Vue3 使用 createApp().component 方式
import { createApp, h } from 'vue';
import Test from './Test.vue';

createApp(Test).component('Comp', { render: () => h('div', '自定义组件') })
  • частьAPIизменение способа его использования (дляtree-shaking)
// Vue2
import Vue from 'vue';

Vue.nextTick(() => {})

// Vue3
import { nextTick } from 'vue';

nextTick(() => {})
  • Приложения
import { createApp } from 'vue';
const app = createApp(); // app 为应用实例
Глобальный API Vue2.x API экземпляра приложения Vue3
Vue.config app.config
Vue.config.productionTip Удалить
Vue.use app.config.isCustomElement
Vue.component app.use
... ...

Уведомление:

  1. Vue3удаленный$on/$once/$offа такжеVue.filter

Vue-Router

Официальный адрес Vue-Router

Основное использование

import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '@/views/home.vue';

const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import(/* webpackChunkName: "about" */ '../views/About.vue');
    }
]

const router = createRouter({
    histroy: createWebHashHistory(),
    routes
})

export default router;

Vuex

Официальный адрес Vuex

Основное использование

// store
import { createStore } from 'vuex';

export default createStore({
	state: {}, // 状态
    getters: {}, // 获取状态
	mutations: {}, // 同步修改状态
    actions: {}, // 异步修改状态
    modules: {} // 模块
})
// template
<template>
    ...
</template>
<script>
import { useStore } from 'vuex';
export default defineComponent({
    setup() {
        const store = useStore(); // 创建store实例
        ...
    }
})
</script>

Дизайн структуры полного магазина

Если проект относительно небольшой, вы можете обратиться к этой структуре каталогов

существуетstoreСоздайте четыре подкаталога и один файл в каталоге, а именно:

  1. state: содержит состояние, используемое в проекте
  2. getters: Выполните некоторую обработку некоторых состояний перед использованием.
  3. mutations: Статус синхронизированной модификации
  4. actions: Состояние асинхронной модификации
  5. index.jsфайл: для интеграцииstate,getters,mutations,actions

Если проект относительно большой, вы можете обратиться к этой структуре каталогов

существуетstoreСоздайте каталог и файл в каталоге, а именно:

  1. modules: хранить относительно большой модуль проекта, такой как: домашняя страница, мой...
  2. index.jsфайл: для интеграцииmodulesмодуль

НеквалифицированныйVuexДрузья, вы можете прочитать эту статью:Освойте использование и основные принципы Vuex core API на работе.

Vue2.x & Vue3

  1. Vue2.0использоватьflowписать, покаVue3.0Весь исходный кодTypeScriptдля разработки, дружественная к поддержке TS (все свойства размещены вthisОбъект, трудно подтолкнуть к типу данных компонента)
  2. Оптимизация размера исходного кода: удалить частьapi(filter),использоватьtree-shaking(МногоAPIПрикреплено кVueНа прототипе объекта сложно добитьсяTreeShaking)
  3. Оптимизация захвата данных:Vue3использоватьProxy, производительность значительно улучшилась
  4. Скомпилируйте и оптимизируйте:Vue3Реализован статический анализ шаблонов и алгоритм перезаписи различий
  5. Composition API: интегрируйте логику бизнес-кода, извлеките общую логику (с учетомReact HooksВдохновленный.Vue2использоватьmixin- конфликт имен и неясный источник данных)
  6. Пользовательский рендерер: можно использовать для создания собственного рендерера и перезаписи базовой логики рендеринга Vue.
  7. новыйFragment,Teleport,Suspenseи другие встроенные компоненты

Суммировать

Лучший способ изучить новую технологию — это использовать технологию для самостоятельного написания проекта, медленно исследовать и продолжать карабкаться по ямам, и тогда вы постепенно освоитесь ~