Vue3를 빠르게 시작하는 방법은 무엇입니까? 다음 기사에서는 Vue2와 Vue3를 비교하고 Vue2 개발자가 Vue3을 빠르게 시작할 수 있는 방법을 소개합니다. 모든 사람에게 도움이 되기를 바랍니다.
저자는 이전에 Vue2+React 개발자였습니다. 프로젝트는 Vue3에서 직접 시작해야 하므로 빠르게 배우고 React와 관련된 몇 가지 차이점을 비교해 보겠습니다. 읽기 전제 조건: 이미 Vue2 개발을 시작했습니다
. 이 문서에서 논의된 주요 문제: 已经上手了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
Vue2 개발자가 Vue3을 빠르게 시작하는 방법
단일 노드
만 지원합니다. , Vue3 템플릿은 반응 조각과 유사한 Multiple node
를 지원합니다🎜🎜Changes
는 기본적으로 스크립트에 있습니다(Option api -> Composition api). 화면! ! ! 🎜🎜style은 DefinePropertyv-bind
🎜🎜Proxy를 지원합니다.🎜defineProperty는 배열 객체에 대한 심층 모니터링을 구현할 수 없습니다. Proxy
는 더욱 강력한 기능을 갖춘 최신 브라우저 API입니다. . 🎜🎜더 이상 IE를 지원하지 않습니다. Vue2가 Vue3의 일부 업데이트를 즐기고 싶다면 Vue2.7
버전으로 업그레이드하는 것이 좋습니다.🎜🎜🎜🎜TypeScript 지원 Flow
, TypeScript
를 완벽하게 지원할 수 없음(따라서 프로젝트 초기 단계의 기술 선택이 매우 중요함) 🎜🎜Vue3 TypeScript 완전히 다시 작성
, 제공 React 지원과 동일한 TS 🎜🎜🎜🎜새로운 생태학Pina
🎜🎜로 변경할 것을 권장합니다. vitest
등을 포함한 새로운 vite
지원으로 공식은 더 많은 주변 도구를 제공합니다 🎜🎜🎜🎜기타 최적화 더 나은 성능, 더 작은 크기 말할 필요도 없이 🎜🎜<code>이벤트 수신 캐시
는 @click에 바인딩된 함수와 유사하며 여러 번 생성할 필요가 없으며 캐시 핸들러 캐시🎜🎜SSR에 배치됩니다.
: Vue 3.0은 정적 태그를 사용하여 텍스트로 직접 변환합니다. 먼저 JSX를 가상 DOM으로 변환한 다음 가상 DOM을 HTML로 변환하는 React와 비교할 때 Vue3은 🎜🎜후크 사용
)이 훨씬 빠릅니다. > 기존 믹스인을 포기하고 Hooks를 사용하세요. 기존 믹스인의 몇 가지 단점을 해결하세요🎜🎜🎜🎜🎜모르겠습니다. 자세한 내용은 나중에 추가하겠습니다🎜
동적 및 정적 조합
방법을 채택하여 diff 성능을 최적화합니다. 🎜🎜 컴파일 단계를 통해 정적 템플릿을 분석하고 블록 트리를 컴파일 및 생성합니다. 업데이트 성능은 템플릿의 전체 크기
=> 및 동적 콘텐츠의 양
과 관련이 있습니다. 이는 매우 큰 성능 혁신입니다. 렌더링 함수 외부에서 코드를 해제하면 모든 렌더링에서 이러한 객체가 다시 생성되는 것을 방지하여 메모리 사용량을 크게 향상시키고 가비지 수집 빈도를 줄입니다. 🎜🎜poly-repo
mono-repo
독립적
일 수 있습니다. vue.js 예를 들어 사용자가 vue3.0의 반응형 스타일을 사용하려는 경우 vue.js 전체에 의존하는 대신 반응형에만 의존
하면 됩니다. 참조 패키지의 크기이지만 vue2.x는 현재 이를 수행할 수 없습니다. 🎜🎜🎜🎜🎜소스 코드 구조 비교🎜🎜🎜🎜🎜🎜🎜🎜새로운 API🎜🎜🎜🎜🎜🎜🎜🎜🎜결합 API란 무엇인가요? - Vue 공식🎜🎜🎜setup
옵션이 실행됩니다setup
选项在组件被创建之前执行,一旦 props
被解析完成,它就将被作为组合式 API 的入口。await语法
<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) } }
基础类型
的响应式数据.value
调用有一定的心智负担,尤大也明确说了不会支持script中直接访问。究其原因,还是基础类型无法拦截它的变化,当然也有大哥提出用new String('foo')类似的语法对基础类型进行包装。个人感觉直接拿已支持的reactive来搞也不错
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行为引用类型
的响应式数据proxy对象
递归的
,改变某一层的值都会递归的调用一遍,重新渲染dom。直接解构
,响应性会丢失,需要用toRefs
包裹。引用类型直接改变引用地址也会导致响应式丢失readonly
将reactive的值更改为只读shallowReactive
. propsawait 구문
을 직접 작성할 수 있습니다.<script lang="ts" setup>에서 직접 사용 가능 </ code> 또는 <p><pre class="brush:php;toolbar:false">import { reactive, toRefs } from &#39;vue&#39;
const book = reactive({
author: &#39;Vue Team&#39;,
year: &#39;2020&#39;,
title: &#39;Vue 3 Guide&#39;,
description: &#39;You are reading this book right now ;)&#39;,
price: &#39;free&#39;
})
let { author, title } = toRefs(book)
title.value = &#39;Vue 3 Detailed Guide&#39; // 我们需要使用 .value 作为标题,现在是 ref
console.log(book.title) // &#39;Vue 3 Detailed Guide&#39;<h3 data-id="heading-8"><p>2, ref<img src="https://img.php.cn/upload/image/658/946/527/1658836117320807.png" title="1658836117320807.png" alt="Vue2 개발자가 Vue3을 빠르게 시작하는 방법에 대해 이야기해 보겠습니다."/>🎜🎜ref를 <code>내보내기 기본값</script></code>과 함께 사용하여 <code> 기초 </code> 🎜🎜템플릿 유형의 반응형 데이터는 기본적으로 데이터를 표시하기 위해 값을 호출합니다. 스크립트에서 React ref와 유사한 🎜🎜를 호출하려면 <code>.value</code>를 사용해야 합니다. .current를 사용하여 값을 가져오고 vue3은 값을 가져옵니다. 🎜🎜Ref의 본질은 Reactive를 통해 만들어집니다. Ref(10)=>Reactive({value:10})🎜🎜<blockquote>🎜직접 지원하지 않는다는 정신적 부담도 있음을 분명히 했습니다. 스크립트 액세스. 그 이유는 기본 유형이 변경 사항을 가로챌 수 없기 때문입니다. 물론 일부 사람들은 기본 유형을 래핑하기 위해 new String('foo') 과 유사한 구문을 사용하도록 제안했습니다. 개인적으로 지원되는 리액티브를 직접 사용하면 좋을 것 같아요🎜</blockquote>
<h4 data-id="heading-9">🎜관련 api🎜</h4>🎜🎜<code>Ref</code> ts 정의import { type Ref } from 'vue';🎜🎜<code>isRef</code> ref 객체인지 확인합니다. 일반적으로 ref, toRef, toRefs🎜🎜<code>toRefs</code>에 의해 생성된 변수는 <code>반응형 객체</code>를 단일 반응형 객체🎜🎜<code>shallowRef</code>로 분해하여 추적 자체를 생성합니다. .value는 참조를 변경하지만 해당 값을 반응형으로 만들지는 않습니다. 이는 페이지 DOM을 강제로 업데이트하기 위해 ref🎜🎜<code>triggerRef</code>와 동일한 구조로 비반응형 변수를 생성하는 것으로 간단히 이해됩니다. 생성된 참조가 변경되지 않았더라도 DOM을 업데이트하려면 🎜🎜<code>customRef</code>를 사용하여 계산된 것과 유사한 get 및 set을 제공하고 참조 동작을 사용자 정의할 수 있습니다🎜🎜<h3 data-id="heading-10"> 🎜3.reactive🎜🎜🎜🎜reactive는 <code>참조 유형</code>의 반응형 데이터를 생성하는 데 사용됩니다.🎜🎜Reactive의 본질은 데이터의 각 레이어를 <code> code>프록시 객체</code>🎜 🎜Reactive의 반응성은 기본적으로 <code>재귀적</code>입니다. 특정 레이어의 값을 변경하면 DOM을 다시 렌더링하기 위해 재귀적으로 호출됩니다. 🎜🎜<code>직접 해체</code>하면 응답성이 손실되므로 <code>toRefs</code>로 래핑해야 합니다. 참조 유형의 참조 주소를 직접 변경하면 응답성이 저하될 수도 있습니다🎜🎜<h4 data-id="heading-11">🎜관련 api🎜</h4>🎜🎜<code>읽기 전용</code> Read-only🎜🎜<code>shallowReactive</code>에 대한 반응 값은 얕은 데이터에만 응답할 수 있습니다. 깊은 데이터인 경우 값만 변경하고 뷰🎜🎜<pre class="brush:php;toolbar:false"><script>
import { onMounted } from &#39;vue&#39;;
const getUserInfo = () => {
console.log(&#39;获取用户信息&#39;);
};
onMounted(getUserInfo);
</script></pre>🎜🎜4. 🎜🎜셋업은 생성된 그대로 사용하고, 다른 이름은 변경해서 사용하는데 큰 차이는 없습니다🎜<pre class="brush:php;toolbar:false">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
})</pre>🎜🎜🎜<h3 data-id="heading-13"><strong>5、watch & watchEffect</strong></h3>
<h4 data-id="heading-14"><strong>watch</strong></h4>
<ul>
<li>功能和vue2一致</li>
<li>watch(监听参数,变化回调,配置参数)</li>
<li>注意监听对象的单个属性:<code>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组件库
위 내용은 Vue2 개발자가 Vue3을 빠르게 시작하는 방법에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!