предисловие
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
;
-
props
Представляет свойство, переданное из родительского компонента, и значение является адаптивным. Если значение изменить, страница будет обновлена. Следовательно,props
Деструктуризация невозможна, но вы можете использоватьtoRefs
Проведите деструктуризацию, иначе он потеряет отзывчивость. -
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>
Уведомление:
-
reactive
похожий наVue2
серединаVue.observable()
- Если вы хотите легко использовать его в модуле, вы можете использовать
toRefs
экспорт -
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, [опции] )
-
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>
-
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
разница?
-
watch
это свойство, которое необходимо передать для мониторинга, иwatchEffect
заключается в автоматическом сборе зависимостей -
watch
Вы можете увидеть изменение значения свойства до и после, а такжеwatchEffect
нет -
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 |
... | ... |
Уведомление:
-
Vue3
удаленный$on/$once/$off
а такжеVue.filter
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
Основное использование
// 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
Создайте четыре подкаталога и один файл в каталоге, а именно:
-
state
: содержит состояние, используемое в проекте -
getters
: Выполните некоторую обработку некоторых состояний перед использованием. -
mutations
: Статус синхронизированной модификации -
actions
: Состояние асинхронной модификации -
index.js
файл: для интеграцииstate
,getters
,mutations
,actions
Если проект относительно большой, вы можете обратиться к этой структуре каталогов
существуетstore
Создайте каталог и файл в каталоге, а именно:
-
modules
: хранить относительно большой модуль проекта, такой как: домашняя страница, мой... -
index.js
файл: для интеграцииmodules
модуль
НеквалифицированныйVuex
Друзья, вы можете прочитать эту статью:Освойте использование и основные принципы Vuex core API на работе.
Vue2.x & Vue3
-
Vue2.0
использоватьflow
писать, покаVue3.0
Весь исходный кодTypeScript
для разработки, дружественная к поддержке TS (все свойства размещены вthis
Объект, трудно подтолкнуть к типу данных компонента) - Оптимизация размера исходного кода: удалить часть
api(filter)
,использоватьtree-shaking
(МногоAPI
Прикреплено кVue
На прототипе объекта сложно добитьсяTreeShaking
) - Оптимизация захвата данных:
Vue3
использоватьProxy
, производительность значительно улучшилась - Скомпилируйте и оптимизируйте:
Vue3
Реализован статический анализ шаблонов и алгоритм перезаписи различий -
Composition API
: интегрируйте логику бизнес-кода, извлеките общую логику (с учетомReact Hooks
Вдохновленный.Vue2
использоватьmixin
- конфликт имен и неясный источник данных) - Пользовательский рендерер: можно использовать для создания собственного рендерера и перезаписи базовой логики рендеринга Vue.
- новый
Fragment
,Teleport
,Suspense
и другие встроенные компоненты
Суммировать
Лучший способ изучить новую технологию — это использовать технологию для самостоятельного написания проекта, медленно исследовать и продолжать карабкаться по ямам, и тогда вы постепенно освоитесь ~