Сейчас 12 часов после просмотра нового поколения рэпа сегодня, и видя, что все равно уже так поздно, я не сплю и напишу документ.Я немного сонный позже... Пожалуйста, потерпите меня
Хватит нести чушь и начни прямо
Вы можете выбрать способ создания
я до сих пор пользуюсь подставками
Обновление (т.е. переустановка)
npm install -g @vue/cli # OR yarn global add @vue/cli
vue create hello-vue3
Разница между следующим и оригиналом в том, что есть больше опциональных версий, вы можете выбрать vue3, чтобы начать
Во-первых, ключевые моменты
Во-первых, значительное главное (после трех лучших трех третий пренебрегают)
1.1. composition API
Независимо от сравнения между API параметров и API композиции, давайте начнем непосредственно с API композиции.
точка входа API композицииsetupфункция
Создание адаптивных данныхrefа такжеreactive
ref
Функция ref принимает один аргумент и возвращает реактивный объект ref.
смотреть прямо на каштаны
<template>
<div>
{{num}}
</div>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
const num = ref(1);
return { num };
},
};
</script>
То есть это то же самое, что и это написано в vue2.x
data(){
return {
num:1
}
}
Стоит отметить, что: ref возвращает объект, и его значение нужно получить через его атрибут value
то естьnum.value. Однако он будет автоматически решаться при использовании в шаблонах. То есть шаблон в каштане выше использует num напрямую, и есть еще один случай, который можно решить автоматически.
Кроме того, теперь вы можете понять, что ref используется для того, чтобы сделать простые типы данных реактивными.
reactive
ref отвечает за простые данные data, тогда reactive должен сделать данные ссылочного типа реактивными
смотреть прямо на каштаны
<template>
<div>{{num}}{{obj.name}}</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
setup() {
const num = ref(1);
const obj = reactive({
name: "gxb",
age: 18,
});
return { num, obj };
},
};
</script>
Другой случай, когда вышеуказанный объект ref автоматически разворачивается, здесь как свойство объекта параметра реактивной функции.
который:
const num = ref(1);
const obj = reactive({
name: "gxb",
age: 18,
num
});
Стоит отметить, что: не используйте его по своему желанию... грамматика или деконструкция, иначе будет потеряна отзывчивость, а последняя инструментальная функция будет введена с каштанами.
readonly
Эта функция, параметр может быть реактивным или нормальным объектом или ссылкой. Возвращает прокси только для чтения (глубокий)
каштан
вычислил и смотри
computed
Computed — это функция, ей нужно передать функцию-получатель. Его возвращаемое значение представляет собой объект ref, который нельзя изменить вручную.
каштан
<template>
<div>{{num2}}</div>
</template>
<script>
import { ref, reactive, computed } from "vue";
export default {
setup() {
const num = ref(1);
const obj = reactive({
name: "gxb",
age: 18,
num,
});
const num2 = computed(() => num.value + 1);
return { num, obj, num2 };
},
};
</script>
Обратите внимание, что его нельзя изменить
Такие как
const num2=computed(()=>num.value+1)
num2.value++
Если вам нужен тот, который можно изменить, вам нужно передать объект с функциями get и set
<template>
<div>{{num2.value}}</div>
</template>
<script>
import { ref, reactive, computed } from "vue";
export default {
setup() {
const num = ref(1);
const obj = reactive({
name: "gxb",
age: 18,
num,
});
const num2 = computed({
get:()=>num,
set:value=>num.value=value
});
num2.value=3
return { num, obj, num2 };
},
};
</script>
Следует отметить, что в это время объект ref num2 не будет автоматически разворачиваться.
watch
монитор один
<template>
<div>{{num2.value}}</div>
</template>
<script>
import { ref, reactive, computed, watch } from "vue";
export default {
setup() {
const obj = reactive({
name: "gxb",
age: 18,
num,
});
watch(
() => obj.name,
(name, preName) => {
console.log(`new ${name}---old ${preName}`);
}
);
setTimeout(() => {
obj.name = "zhangsan";
}, 1000);
return { obj };
},
};
</script>
В дополнение к приведенной выше функции получения с возвращаемым значением, первый параметр также может быть объектом ref.
который
<template>
<div></div>
</template>
<script>
import { ref, reactive, computed, watch } from "vue";
export default {
setup() {
const obj = reactive({
name: "gxb",
age: 18,
num,
});
const num = ref(0);
watch(num, (name, preName) => {
console.log(`new ${name}---old ${preName}`);
});
setTimeout(() => {
num.value = 2;
}, 1000);
return { obj };
},
};
</script>
контролировать несколько
То есть, пока изменяется одно из num или obj.name, запускается обратный вызов обработки слушателя.
<template>
<div></div>
</template>
<script>
import { ref, reactive, computed, watch } from "vue";
export default {
setup() {
const obj = reactive({
name: "gxb",
age: 18,
num,
});
const num = ref(0);
watch([num, ()=>obj.name], ([newNum, newName], [oldNum, oldName]) => {
console.log(`new ${(newNum)},${(newName)}---old ${(oldNum)},${oldName}`);
});
setTimeout(() => {
num.value = 6;
// obj.name = "zhangsan";
}, 1000);
return { obj };
},
};
</script>
крючки жизненного цикла
каштан
import { onMounted, onUpdated, onUnmounted } from 'vue'
const MyComponent = {
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
},
}
Соответствует хукам 2.x
реквизит и это
props
Первым параметром, полученным при настройке функции входа, является реквизит.
каштан
Тут нужно быть внимательным, не разбирать невзначай
избавить от неприятностей
props: {
data: String,
},
setup({ data }) {
console.log(data);
}
Разрушение делает его невосприимчивым
this
В версии 2.x легко взять экземпляр экземпляра компонента, обычно прямо this, но настройка другая.
Но в экземпляре компонента есть много API, которые нам все еще нужно использовать.
Итак, второй параметр настройки — объект контекста.
Каштан: отправить пользовательское событие
Стоит отметить, что этот контекст только выборочно раскрывает некоторые атрибуты, такие как вышеупомянутые emit и attrs, slots
Внедрение зависимостей и ссылки
внедрение зависимости
Это в основном то же самое, что и предоставление и внедрение vue2.x.
каштан
Пример компонента, который я использую для простоты схемы
Их отзывчивость должна проявляться сама по себе (например, при использовании ref)
Refs
Возьмите следующий узел
<template>
<div ref="test">test</div>
</template>
<script>
import {
ref,
reactive,
computed,
watch,
provide,
inject,
onMounted,
} from "vue";
export default {
setup() {
const test = ref(null);
onMounted(() => {
console.log(test.value);
});
return { test };
},
};
</script>
некоторые полезные функции
Давайте сначала напишем каштан, который уничтожает прокси объекта ответа, сгенерированный реактивным
Первое нормальное письмо
<template>
<div ref="test">
{{obj.age}}
<button @click="obj.age++">add</button>
</div>
</template>
<script>
import { ref, reactive, computed, watch, provide, inject, readonly } from "vue";
export default {
props: {
data: String,
},
setup(props, context) {
console.log(props.data);
context.emit("test");
const obj = reactive({
name: "gxb",
age: 18,
});
return { obj };
},
};
</script>
Использовать расширенный синтаксис
<template>
<div ref="test">
{{age}}
<button @click="age++">add</button>
</div>
</template>
<script>
import { ref, reactive, computed, watch, provide, inject, readonly } from "vue";
export default {
props: {
data: String,
},
setup(props, context) {
console.log(props.data);
context.emit("test");
const obj = reactive({
name: "gxb",
age: 18,
});
return { ...obj };
},
};
</script>
Деконструкция тоже не работает.
<template>
<div ref="test">
{{age}}
<button @click="age++">add</button>
</div>
</template>
<script>
import { ref, reactive, computed, watch, provide, inject, readonly } from "vue";
export default {
props: {
data: String,
},
setup(props, context) {
console.log(props.data);
context.emit("test");
const obj = reactive({
name: "gxb",
age: 18,
});
const { age } = obj;
return { age };
},
};
</script>
Принцип этого также очень прост.Внутренний принцип реактивного — это прокси, который работает с возвращенным экземпляром прокси.
Начнем с нескольких функций инструмента
- unref, если параметр является ссылкой, он возвращает значение атрибута ссылки, в противном случае он возвращает себя
- toRef, создает ссылку на свойство реактивного объекта
- toRefs, преобразует отзывчивый объект в обычный объект, где каждое свойство обычного объекта является ссылкой
- isRef, чтобы определить, является ли значение ссылкой
- isProxy, чтобы определить, представлен ли объект
reactiveилиreadonlyметод создания прокси. - isReactive, чтобы определить, активирован ли объект
reactiveСоздал реактивный прокси - isReadonly, чтобы определить, читается ли объект
readonlyСоздал прокси только для чтения.
Просто напишите пример для 2 и 3.
toRef, который превращает свойство реактивного объекта в ссылку
Что вы имеете в виду, или посмотрите на каштаны выше, которые уничтожают отзывчивость
Исправьте это (вы можете извлечь одно из его свойств, чтобы сделать отзывчивую ссылку, и они все еще связаны друг с другом)
<template>
<div ref="test">
{{age}}
<button @click="age++">add</button>
</div>
</template>
<script>
import {
ref,
reactive,
computed,
watch,
provide,
inject,
readonly,
toRef,
} from "vue";
export default {
props: {
data: String,
},
setup(props, context) {
const obj = reactive({
name: "gxb",
age: 18,
});
const age=toRef(obj, "age");
watch(()=>obj.age,(newAge,oldAge)=>{
console.log(newAge);
})
return { age };
},
};
</script>
toRefs заключается в преобразовании всех свойств объекта в refs, что легче исправить
<template>
<div ref="test">
{{age}}
<button @click="age++">add</button>
</div>
</template>
<script>
import {
ref,
reactive,
computed,
watch,
provide,
inject,
readonly,
toRef,
toRefs
} from "vue";
export default {
props: {
data: String,
},
setup(props, context) {
const obj = reactive({
name: "gxb",
age: 18,
});
const obj02=toRefs(obj);
return { ...obj02 };
},
};
</script>
1.2. Teleport
Портал, как следует из названия
Сценарий: В некоторых компонентах нам может понадобиться функция модального бокса.Хотя логически этот модальный бокс принадлежит компоненту, реальная операция обычно требует повесить этот бокс на тело. Компонент Teleport здесь, чтобы помочь нам справиться с этим.
Приходите посмотреть на каштаны
Предположим, что в компоненте должен быть модальный
<template>
<div>
<model></model>
</div>
</template>
<script>
import Model from './model'
export default {
components:{Model}
}
</script>
Компонент модального окна
<template>
<div>
<button @click="flag=true">点击</button>
<teleport to="body">
<div v-if="flag">
<div>模态框</div>
</div>
</teleport>
</div>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
const flag = ref(false);
return { flag };
},
};
</script>
То есть функция компонента телепорта заключается в переносе элементов тега телепорта в тело.
посмотри на уровень
1.3. Fragments
Это легче понять
Оказывается, это может быть только так: то есть допускается существование только одного самого внешнего родительского элемента.div
<template>
<div>
...
</div>
</template>
Теперь можно больше
<template>
<div>
...
</div>
<div>
...
</div>
...
</template>
1.4. Emits Component Option
1.4.1 Отправка пользовательских событий
Ключевой момент здесь: то есть есть еще один вариант отправки событийemits
То есть, когда мы используем emit для повторной отправки события в будущем, нам нужно указать имя отправленного события в параметрах.
Каштан:
<template>
<div>
<button @click="$emit('test')">点击</button>
</div>
</template>
<script>
export default {
emits: ["test"],
};
</script>
Примечание. Если вы отправляете собственное событие здесь и не помещаете это событие в параметр emits, мониторинг его родительского компонента будет запущен дважды.
<template>
<div>
<button @click="$emit('click')">点击</button>
</div>
</template>
<script>
export default {
// emits: ["click"],
};
</script>
1.4.2 v-model
в vue3v-model, свойстваmodelValueИспользуемое событиеupdate:modelValue (и синхронизация была удалена в 3)
каштан
родительский компонент
<template>
<div id="nav">
{{data}}
<test05 v-model="data"></test05>
</div>
</template>
<script>
import { ref } from "vue";
import Test05 from "./components/test05";
export default {
components: { Test05 },
setup() {
const data=ref('gxb')
return {data};
},
};
</script>
Подсборка
<template>
<div>
<input type="text" :value="modelValue" @input="$emit('update:modelValue',$event.target.value)" />
</div>
</template>
<script>
export default {
props:{
modelValue:String
},
emits:['update:modelValue']
}
</script>
Настройте имя атрибута.В vue2.x параметр модели можно использовать для указания переданного имени атрибута и указания события, которое будет использоваться этой v-моделью. Атрибуты также можно настроить в vue3.
каштан
Родительский компонент (т.е. указать привязку после v-модели)
<test05 v-model:foo="data"></test05>
Подсборка
<template>
<div>
<input type="text" :value="foo" @input="$emit('update:foo',$event.target.value)" />
</div>
</template>
<script>
export default {
props:{
foo:String
},
emits:['update:foo']
}
</script>
В компоненте может быть записано несколько директив v-model.
Каштан:
родительский компонент
<test01 v-model:foo="a" v-model:bar="b"></test01>
Подсборка
<template>
<div>
<input type="text" :value="foo" @input="$emit('update:foo',$event.target.value)" />
<input type="text" :value="bar" @input="$emit('update:bar',$event.target.value)" />
</div>
</template>
<script>
export default {
props: {
foo: String,
bar: String,
},
emits: ["update:foo", "update:bar"],
setup(props) {
return {};
},
};
</script>
1.5. createRendererAPI
Пользовательский рендерер соответствует его названию. Его основная функция заключается в том, что мы можем настроить путь от виртуального DOM к DOM. Увидев каштаны 3 или 4 больших парней, они все рисовали картинки на холсте. Я не могу придумать здесь никаких каштанов, поэтому не буду писать первым
2. Другое
2.1 Global API
В vue2.x нет концепции приложения, а так называемое «приложение» в vue2.x — это просто экземпляр, созданный Vue. Но некоторые глобальные API в 2.x (такие как миксины, использование, компонент и т. д.) находятся непосредственно в конструкторе Vue.
То есть, если есть «приложения», использующие новый Vue ниже, эти глобальные API могут легко вызвать загрязнение.
Давайте посмотрим на входной файл vue3.
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
Теперь, когда у нас есть createApp, этот метод возвращает экземпляр приложения.
Возьмите компонент, чтобы написать каштан
import { createApp, h } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App)
.component('test06', {
render() {
return h('div', {}, '全局组件')
}
})
.use(store)
.use(router)
.mount('#app')
Соответственно меняются и другие API, например, официальный сайт.
Global API Treeshaking
Официальный сайт — Vue.nextTick(), например, глобальный API.
Что это за встряхиватель деревьев?
Из этого предложения можно понять, что эти API написаны без разбора на конструкторе Vue, если мы не используем эти API в приложении. Итак, когда вы упаковываете эти вещи, это приводит к потере производительности, а также к увеличению размера упаковки?
Поэтому в vue3 использование nextTick также нужно импортировать из vue.
import { nextTick } from 'vue'
nextTick(() => {
...
})
Другие затронутые API
2.2 Template Directives
v-model
v-model было написано выше, удалено.sync, унифицировано с использованием v-модели
v-если, v-для приоритетной задачи
В версии 2.x высокий приоритет имеет v-for, а в версии 3.0 — v-if.
2.3 Components
функциональные компоненты
Поскольку улучшение производительности функциональных компонентов в vue3 теперь незначительно, рекомендуется использовать компоненты состояния.
И здесь функциональные компоненты могут быть объявлены только через чистые функции и могут принимать только реквизиты и контекст (а также генерировать, слоты, атрибуты)
простой пример
Поленитесь тут, принесите каштаны с официального сайта
vue2.x
// Vue 2 Functional Component Example
export default {
functional: true,
props: ['level'],
render(h, { props, data, children }) {
return h(`h${props.level}`, data, children)
}
}
vue3, разница заключается в том, что в дополнение к проблеме изменения функции h, упомянутой ниже, а также к проблеме параметра, упомянутой выше, еще одно изменение заключается в удаленииfunctional: true,
import { h } from 'vue'
const DynamicHeading = (props, context) => {
return h(`h${props.level}`, context.attrs, context.slots)
}
DynamicHeading.props = ['level']
export default DynamicHeading
сравнение одного файла
2.x
// Vue 2 Functional Component Example with <template>
<template functional>
<component
:is="`h${props.level}`"
v-bind="attrs"
v-on="listeners"
/>
</template>
<script>
export default {
props: ['level']
}
</script>
3.0 разница убранаfunctional, слушатель помещается в $attrs и может быть удален
<template>
<component
v-bind:is="`h${props.level}`"
v-bind="$attrs"
/>
</template>
<script>
export default {
props: ['level']
}
</script>
Асинхронные компоненты
А как насчет асинхронных компонентов?
const asyncPage = () => import('./NextPage.vue')
или с вариантами
const asyncPage = {
component: () => import('./NextPage.vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
}
Но в vue3 все иначе, здесь новый APIdefineAsyncComponentИспользуется для явного определения асинхронных компонентов.
то есть
const asyncPage = defineAsyncComponent(() => import('./NextPage.vue'))
или
const asyncPageWithOptions = defineAsyncComponent({
loader: () => import('./NextPage.vue'),
delay: 200,
timeout: 3000,
errorComponent: ErrorComponent,
loadingComponent: LoadingComponent
})
Если внимательно посмотреть, то можно увидетьcomponentизменился наloader
Еще одно отличие состоит в том, что в 2.x можно получить параметры функцииresolve,reject,3.0 не допускается, но должен возвращать обещание
2.4 Render Function
Изменения функции рендеринга
То есть исходная функция h выглядит так
export default {
render(h) {
return h('div')
}
}
И теперь функцию h нужно снова импортировать из vue.
На самом деле, у меня есть каштан, который я уже использовал, и я верну его снова.
import { createApp, h } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App)
.component('test06', {
render() {
return h('div', {}, '全局组件')
}
})
.use(store)
.use(router)
.mount('#app')
Так же есть изменение атрибутов, прямо каштаны берите с официального сайта.
Формат атрибута узла в 2.x
{
class: ['button', 'is-outlined'],
style: { color: '#34495E' },
attrs: { id: 'submit' },
domProps: { innerHTML: '' },
on: { click: submitForm },
key: 'submit-button'
}
В 3.0 эти свойства больше не являются вложенными, они сглажены (это больше похоже на что-то на узле DOM).
{
class: ['button', 'is-outlined'],
style: { color: '#34495E' },
id: 'submit',
innerHTML: '',
onClick: submitForm,
key: 'submit-button'
}
Аспект слота
устаревший$scopedSlots,использовать$slots
В vue2.x компонент использует функцию рендеринга, чтобы получить такой слот.
<script>
export default {
render(h) {
return h('div',{},this.$scopedSlots.default)
},
}
</script>
Это имеет место в vue3.x
<script>
import {h} from 'vue'
export default {
props:{
data:String
},
render() {
return h('div',{},this.$slots.default())
},
}
</script>
2.5 Custom Elements
Белый список настраиваемых элементов
Например, для некоторых специальных компонентов мы хотим игнорировать компиляцию vue для специальных целей.
каштан
Поместите зарегистрированный компонент непосредственно в компонент
<test08></test08>
Если вы не хотите эту ошибку, поместите ее в белый список
Использовать версию инструментов сборки
rules: [
{
test: /\.vue$/,
use: 'vue-loader',
options: {
compilerOptions: {
isCustomElement: tag => tag === 'test08'
}
}
}
// ...
]
Скомпилированная версия во время выполнения
const app = Vue.createApp({})
app.config.isCustomElement = tag => tag === 'test08'
можно использовать только в<component>начальство
но<component :is="componentId"></component> В дополнение к этому, нам также может понадобиться использовать is в других местах, что нам делать?
Поэтому инструкция v-is была введена в vue3.
Вот об этом, это почти то же самое. Я больше не могу... Спокойной ночи, сладких снов.