Wie kann ich schnell mit Vue3 beginnen? Der folgende Artikel vergleicht Vue2 und Vue3 und stellt vor, wie Vue2-Entwickler schnell mit Vue3 beginnen können. Ich hoffe, dass er für alle hilfreich ist!
Der Autor war zuvor ein Vue2+React-Entwickler. Da das Projekt direkt mit Vue3 gestartet werden muss, werde ich es schnell lernen und einige Unterschiede im Zusammenhang mit React vergleichen. Voraussetzungen zum Lesen: Haben bereits mit der Entwicklung von Vue2 begonnen
Die in diesem Artikel behandelten Hauptthemen: 已经上手了Vue2的开发
,本文主要聊的问题:
Vue3的全新特性
Vue2和Vue3的一些区别
Vue2开发者如何快速上手Vue3
Vue3和React的简单比对
使用Vue3编写组件库
(学习视频分享:vue视频教程)
单节点
,Vue3 template支持多节点
,类似react fragments变化
基本都在script中(Option api -> Composition api)不会再看见满屏的this了!!!v-bind
Proxy
是浏览器最新api,功能更加强大。Vue2.7
版本Flow
,没法完美支持TypeScript
(所以项目初期技术选型很重要)完全重写
,提供和React一样的TS支持Pina
vite
支持,包括vitest
等,官方提供周边工具更多了性能更好,体积更小
就不用说了事件监听缓存
,类似@click绑定的函数,无需多次创建,放在了cacheHandler缓存中SSR
:Vue 3.0 会将静态标签直接转化为文本,相比 React 先将 JSX 转化为虚拟 DOM,再将虚拟 DOM 转化为 HTML,这一点Vue3的速度要快很多Use Hooks
放弃过去的mixins,使用Hooks解决过去mixins的一些缺点了解的不多,后续再补充
动静结合
的方法,优化diff性能模版整体大小相关
=》与动态内容的数量相关
,这是一个非常大的性能突破。将代码提升到渲染函数之外,这样可以避免在每次渲染时重新创建这些对象,从而大大提高内存使用率并减少垃圾回收的频率。poly-repo
mono-repo
独立于
vue.js去使用,这样例如用户想要使用vue3.0的响应式,可以单独依赖reactive
Wie Vue2-Entwickler schnell mit Vue3 beginnen können
Verwendung von Vue3 zum Schreiben von Komponentenbibliotheken
(Teilen von Lernvideos: vue-Video-Tutorial)
einzelne Knoten
, Vue3-Vorlage unterstützt Mehrere Knoten
, ähnlich wie React-Fragmente🎜🎜Änderungen
sind grundsätzlich im Skript (Option api -> Composition api). der Bildschirm! ! ! 🎜🎜style unterstützt v-bind
🎜🎜Proxy anstelle von definePropertyProxy
ist die neueste Browser-API und verfügt über eine höhere Leistung Funktionen. 🎜🎜Unterstützt IE nicht mehr. Wenn Vue2 einige der von Vue3 bereitgestellten Updates nutzen möchte, können Sie ein Upgrade auf die Vue2.7
-Version in Betracht ziehen. 🎜🎜🎜🎜TypeScript-Unterstützung Flow
kann TypeScript
nicht perfekt unterstützen (daher ist die Technologieauswahl in der frühen Phase des Projekts sehr wichtig) 🎜🎜Vue3 TypeScript komplett neu geschrieben
, Bereitstellung das gleiche TS wie React Support 🎜🎜🎜🎜New EcologyPina
🎜🎜 Mit der neuen vite-Unterstützung, einschließlich <code>vitest
usw., bietet der Beamte mehr periphere Tools 🎜🎜🎜🎜Andere Optimierungen Bessere Leistung, kleinere Größe Es versteht sich von selbst, dass 🎜🎜<code>Event-Listening-Cache
, ähnlich der durch @click gebundenen Funktion, nicht mehrmals erstellt werden muss und im CacheHandler-Cache abgelegt wird🎜🎜SSR
: Vue 3.0 verwendet statische Tags, um sie direkt in Text umzuwandeln, was zuerst JSX in virtuelles DOM und dann virtuelles DOM in HTML umwandelt. 🎜🎜Verwenden Sie Hooks
Geben Sie die früheren Mixins auf und verwenden Sie Hooks. Lösen Sie einige Mängel früherer Mixins🎜🎜🎜🎜🎜Ich weiß es nicht Vieles dazu, ich werde später mehr hinzufügen Zwei virtuelle DOM-Bäume. Vue3 verwendet eineKombination aus dynamischen und statischen
Methoden, um die Diff-Leistung zu optimieren. 🎜🎜 Analysieren Sie die statische Vorlage während der Kompilierungsphase, kompilieren und generieren Sie einen Blockbaum. Die Aktualisierungsleistung hängt von derGesamtgröße der Vorlage
=> und derMenge des dynamischen Inhalts
ab. Dies ist ein sehr großer Leistungsdurchbruch. Durch das Entfernen des Codes außerhalb der Renderfunktion wird vermieden, dass diese Objekte bei jedem Rendern neu erstellt werden, was die Speichernutzung erheblich verbessert und die Häufigkeit der Speicherbereinigung verringert. 🎜🎜🎜Quellcodeverwaltung🎜
🎜vue2
poly-repo
🎜vue2.x-Quellcode wird in gehostet das src-Verzeichnis und dann nach Funktionen aufteilen in Compiler (Code im Zusammenhang mit der Vorlagenkompilierung), Kern (allgemeiner Laufzeitcode unabhängig von der Plattform), Plattformen (plattformspezifischer Code), Server (Code im Zusammenhang mit serverseitigem Rendering), sfc (Code zum Parsen einzelner Dateien mit .vue), Shared (gemeinsam genutzter Toolcode) und andere Verzeichnisse🎜🎜🎜🎜vue3
mono-repo
🎜Paket kann
unabhängig
sein vue.js Um es zu verwenden, kann der Benutzer beispielsweise, wenn er den reaktiven Stil von vue3.0 verwenden möchte,sich nur auf reaktiv verlassen
, anstatt sich auf die gesamte vue.js zu verlassen, wodurch die Größe reduziert wird des Referenzpakets, was vue2.x derzeit nicht kann. 🎜🎜🎜🎜🎜Vergleich der Quellcodestruktur🎜🎜🎜🎜🎜🎜🎜🎜Neue API🎜🎜🎜🎜🎜🎜🎜🎜🎜Was ist eine kombinierte API? - Vue-Beamter🎜🎜🎜Kann als beforeCreate verwendet werden und den Lebenszyklus von Vue2 erstellenKann
- Das Problem der Wartungsschwierigkeiten, die durch OptionsApi verursacht wurden, wenn die Komponenten in der Vergangenheit zu lang waren, wurde gelöst.
- Die Logik kann als Ganzes wiederverwendet werden.
- Alle APIs werden durch Import eingeführt, sehr benutzerfreundlich für Tree-Shaking, keine Funktionen verwendet, und sie werden gepackt. Es wird bereinigt und die Größe des Pakets wird reduziert. 1. Setup. Die neue Option
setup
wird ausgeführt, bevor die Komponente erstellt wirdprops
ist Nach dem Parsen wird es als Einstiegspunkt für die zusammengesetzte API verwendet.await syntax
direkt schreiben
- Direkt in der SFC-Einzeldateikomponente verwenden
<script lang="ts" setup> </ code>, oder Sie können <code>setup</script>
选项在组件被创建之前执行,一旦props
被解析完成,它就将被作为组合式 API 的入口。- 可以当做Vue2的beforeCreate和create生命周期用
- 可直接写
await语法
- SFC单文件组件中直接使用
<script lang="ts" setup></script>
即可,或者也可以结合export default
使用<script> const result = await Http.get('/getUserInfo') </script> // or export default { setup(props, context) { // Attribute (非响应式对象,等同于 $attrs) console.log(context.attrs) // 插槽 (非响应式对象,等同于 $slots) console.log(context.slots) // 触发事件 (方法,等同于 $emit) console.log(context.emit) // 暴露公共 property (函数) console.log(context.expose) } }Nach dem Login kopieren2、ref
- ref 用来创建
基础类型
的响应式数据- template中默认调用value显示数据,script中需要使用
.value
调用- 和react ref差不多,react是.current获取值,vue3是.value。
- Ref的本质是通过Reactive创建的,Ref(10)=>Reactive({value:10})
有一定的心智负担,尤大也明确说了不会支持script中直接访问。究其原因,还是基础类型无法拦截它的变化,当然也有大哥提出用new String('foo')类似的语法对基础类型进行包装。个人感觉直接拿已支持的reactive来搞也不错
相关api
Ref
ts定义import { type Ref } from 'vue';
isRef
判断是否为ref对象。一般是ref,toRef,toRefs创建的变量toRefs
将reactive对象
解构为单个响应式对象shallowRef
创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的,简单理解为创建一个和ref相同结构的非响应式变量triggerRef
强制更新页面DOM。即使创建的ref没有变,想更新dom可以用customRef
提供类似于computed的get和set,可自定义ref行为3、reactive
- reactive 用来创建
引用类型
的响应式数据- reactive的本质是将每一层的数据都解析成
proxy对象
- reactive 的响应式默认都是
递归的
,改变某一层的值都会递归的调用一遍,重新渲染dom。直接解构
,响应性会丢失,需要用toRefs
包裹。引用类型直接改变引用地址也会导致响应式丢失相关api
readonly
将reactive的值更改为只读shallowReactive
import { reactive, toRefs } from 'vue' const book = reactive({ author: 'Vue Team', year: '2020', title: 'Vue 3 Guide', description: 'You are reading this book right now ;)', price: 'free' }) let { author, title } = toRefs(book) title.value = 'Vue 3 Detailed Guide' // 我们需要使用 .value 作为标题,现在是 ref console.log(book.title) // 'Vue 3 Detailed Guide'Nach dem Login kopieren
export default
verwenden, um den basis Die responsiven Daten vom Typ
template rufen standardmäßig den Wert auf, um Daten anzuzeigen. Im Skript müssen Sie .value
verwenden, um aufzurufen, was React ähnelt verwendet .current, um den Wert zu erhalten, und vue3 tut dies.
🎜Die Essenz von Ref entsteht durch Reactive Zugriff in Skripten. Der Grund dafür ist, dass der Basistyp seine Änderungen nicht abfangen kann. Natürlich haben einige Leute vorgeschlagen, eine ähnliche Syntax wie new String('foo') zu verwenden, um den Basistyp zu umschließen. Persönlich denke ich, dass es gut wäre, die unterstützten Reaktiven direkt zu verwenden definitionimport { type Ref } from 'vue';🎜🎜isRef
Bestimmen Sie, ob es sich um ein Ref-Objekt handelt. Im Allgemeinen werden Variablen, die von ref, toRef, toRefs erstellt werden .value ändert die Referenz, macht ihren Wert jedoch nicht responsiv. Es wird einfach so verstanden, dass eine nicht reagierende Variable mit der gleichen Struktur wie ref🎜🎜triggerRef
erstellt wird, um die Aktualisierung des Seiten-DOM zu erzwingen. Selbst wenn sich die erstellte Referenz nicht geändert hat, können Sie, wenn Sie den Dom aktualisieren möchten, 🎜🎜customRef
verwenden, um Get und Set ähnlich wie berechnet bereitzustellen, und Sie können das Referenzverhalten anpassen🎜🎜Referenztyp
zu erstellen 🎜🎜Das Wesentliche von reaktiv ist, jede Datenebene in proxy-Objekte🎜 🎜Reactives Reaktionsfähigkeit ist standardmäßig rekursiv
. Das Ändern des Werts einer bestimmten Ebene wird rekursiv aufgerufen, um den Dom neu zu rendern. 🎜🎜Direkte Dekonstruktion
, die Reaktionsfähigkeit geht verloren und muss mit toRefs
umschlossen werden. Das direkte Ändern der Referenzadresse des Referenztyps führt ebenfalls zu einem Verlust der Reaktionsfähigkeit Wert von reaktiv auf schreibgeschützt🎜🎜shallowReactive
kann nur auf flache Daten reagieren, es ändert nur den Wert, aber nicht die Ansicht🎜🎜<script> import { onMounted } from 'vue'; const getUserInfo = () => { console.log('获取用户信息'); }; onMounted(getUserInfo); </script>
import { ref, reactive, watch } from 'vue' const counter1 = ref(0) const counter2 = ref(0) // 监听多个 watch([counter1, counter2], (newValue, oldValue) => { console.log('The new counter1 value is: ' + counter1.value) console.log('The new counter2 value is: ' + counter2.value) }) const obj = reactive({ name: 'JJ', age: 18 }) // 深度监听对象 watch(obj, (newValue, oldValue) => { console.log('The new obj value is: ' + obj.value) }, { deep: true, immediate: true }) // watch监听单个属性 watch(() => obj.name, (newValue, oldValue) => { console.log('The new obj value is: ' + obj.value) }, { deep: true, immediate: true })
watch(() => articleInfo.author, (newVal) => {})
,第一个参数为箭头函数返回要监听的目标属性import { ref, reactive, watch } from 'vue' const counter1 = ref(0) const counter2 = ref(0) // 监听多个 watch([counter1, counter2], (newValue, oldValue) => { console.log('The new counter1 value is: ' + counter1.value) console.log('The new counter2 value is: ' + counter2.value) }) const obj = reactive({ name: 'JJ', age: 18 }) // 深度监听对象 watch(obj, (newValue, oldValue) => { console.log('The new obj value is: ' + obj.value) }, { deep: true, immediate: true }) // watch监听单个属性 watch(() => obj.name, (newValue, oldValue) => { console.log('The new obj value is: ' + obj.value) }, { deep: true, immediate: true })
响应式的属性
watchEffect
是拿不到的。显式
指定依赖源,watchEffect - 自动
收集依赖源可以理解为watchEffect 就是配置了{ immediate: true } 的watch
antfu小哥
:推荐在大部分时候用 watch 显式的指定依赖以避免不必要的重复触发,也避免在后续代码修改或重构时不小心引入新的依赖。watchEffect 适用于一些逻辑相对简单,依赖源和逻辑强相关的场景(或者懒惰的场景 )。const stopWatch = watchEffect( (oninvalidate): void => { oninvalidate(() => { console.log("前置校验函数"); }); // 引用了响应式的属性 count console.log("watchEffect count变化", count.value); }, { // 副作用刷新时机 flush 一般使用post // 可选:pre(组件更新前执行)/sync(强制效果始终同步触发)/post(组件更新后执行) flush: "post", // 开发调试 onTrigger() { console.log("开发调试"); }, } );
import { ref, computed } from 'vue' const counter = ref(0) const twiceTheCounter = computed(() => counter.value * 2) // get set写法 const plusOne = computed({ get: () => counter.value + 1, set: (val) => { counter.value = val - 1 }, }) plusOne.value = 1 console.log(counter.value) // 0 counter.value++ console.log(counter.value) // 1 console.log(twiceTheCounter.value) // 2
// template <suspense> <template> <asynccomponent></asynccomponent> </template> <template> <div>loading...</div> </template> </suspense> // script const AsyncComponent = defineAsyncComponent(() => import('./asyncComponent.vue'))
Teleport 是一种能够将我们的模板渲染至指定DOM节点,不受父级style、v-show等属性影响,但data、prop数据依旧能够共用的技术;类似于 React 的 Portal
。之前写react是不怎么用这个属性,vue3这个估计也没多大用。
主要解决的问题 因为Teleport节点挂载在其他指定的DOM节点下,完全不受父级style样式影响
to 属性 插入指定元素位置,body,html,自定义className等等
<teleport> <loading></loading> </teleport>
defineXxxx 无需import即可直接使用
和vue2一致
两者用法,除了pina没有Mutations,差别不大。但是官方推荐的东西,自然有它的各种优点
react中 {{}} => {}
import { ref } from 'vue' let v = ref<string>('') const renderDom = () => { return ( <input> <div> {v.value} </div> > ) } export default renderDom</string>
无需导入xxx,import { reactive,ref } from "vue";
,只需要用即可
自定义组件名称,需要引入插件unplugin-vue-define-options
,并在vite中配置
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import DefineOptions from 'unplugin-vue-define-options/vite'; export default defineConfig({ plugins: [vue(), DefineOptions()], });
不使用插件,也可以通过多写一个script标签来单独写options
<script> export default { name: "TButton", }; </script> <script> defineOptions({ name: 'TButton', }); </script>
或者通过项目配置,指定相关插件配置
import { Directive } from "vue"; const vMove: Directive = { mounted(el: HTMLElement) { let moveEl = el.firstElementChild as HTMLElement; const mouseDown = (e: MouseEvent) => { //鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离 console.log(e.clientX, e.clientY, "-----起始", el.offsetLeft); let X = e.clientX - el.offsetLeft; let Y = e.clientY - el.offsetTop; const move = (e: MouseEvent) => { el.style.left = e.clientX - X + "px"; el.style.top = e.clientY - Y + "px"; console.log(e.clientX, e.clientY, "---改变"); }; document.addEventListener("mousemove", move); document.addEventListener("mouseup", () => { document.removeEventListener("mousemove", move); }); }; moveEl.addEventListener("mousedown", mouseDown); }, };
用了react hook的人都知道很香,vue3支持这个相当不错,能解决很多业务场景的封装
可以当做mixins写
// useWindowResize import { onMounted, onUnmounted, ref } from "vue"; function useWindowResize() { const width = ref(0); const height = ref(0); function onResize() { width.value = window.innerWidth; height.value = window.innerHeight; } onMounted(() => { window.addEventListener("resize", onResize); onResize(); }); onUnmounted(() => { window.removeEventListener("resize", onResize); }); return { width, height }; } export default useWindowResize;
Vue3 的依赖追踪是全自动的,不需要担心传了错误的依赖数组给 useEffect/useMemo/useCallback 从而导致回调中- 使用了过期的值
Vue3 Hook也没React Hook那么多限制,后续用用看怎么样
笔者vue3也刚用不久,如有错误,还请兄弟们指出
本文所有demo都在该仓库中JJ-UI 一款Vue3组件库,参考大佬文章刚刚搭建好,后续会基于这个架子开发自己的vue3组件库
Das obige ist der detaillierte Inhalt vonLassen Sie uns darüber sprechen, wie Vue2-Entwickler schnell mit Vue3 beginnen können. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!