ホームページ >ウェブフロントエンド >Vue.js >vue3の定番テクニックとvue2との違いを整理して共有(一部)
この記事では、ライフサイクルの変更、インスタンスの変更、メソッドの変更など、vue3 と vue2 の違いについての知識を提供します。皆様のお役に立てれば幸いです。
vue3の定番テクニックとvue2との違いを整理して共有(一部) と vue3の定番テクニックとvue2との違いを整理して共有(一部) の間のライフサイクル関数が破棄されたときに変更されたことを確認するのは難しくありません:
beforeDestroy --> beforeUnmount destroyed --> unmounted
其他的区别主要在于书写使用的语言上的差别 在ts中使用 class 类组件书写可以 参考 vue-class-component 或者 vue-property-decorator 书写的风格和vue3の定番テクニックとvue2との違いを整理して共有(一部)的选项式区别不大。 如果使用js书写代码 则应当使用组合式。
特定の変更によって引き起こされる問題は、次の組み合わせになります。書き方を解説。
// 之前(Vue 2.x) Vue.prototype.$http = () => {} Vue.prototype.url= 'http://123' // 之后(Vue 3.x) const app = createApp({}) app.config.globalProperties.$http = () => {} app.config.globalProperties.url= 'http://123'
//=======vue3.x //使用createApp函数来实例化vue, //该函数接收一个根组件选项对象作为第一个参数 //使用第二个参数,我们可以将根 prop 传递给应用程序 import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' createApp(App,{ userName: "blackLieo" }) .use(store) .use(router) .mount('#app') //由于 createApp 方法返回应用实例本身,因此可以在其后链式调用其它方法,这些方法可以在以下部分中找到。 //=======vue2.x import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' Vue({ router, store, render: h => h(App) }).$mount('#app')
//================vue3の定番テクニックとvue2との違いを整理して共有(一部)使用插槽基本上直接使用slot进行操作//其中vue3の定番テクニックとvue2との違いを整理して共有(一部)经历了两次更迭,2.6.0版本slot升级为v-slot<p> <slot></slot> // 具名 作用域插槽 <slot></slot> //默认插槽</p>//父组件调用该组件<test> <template> <p>默认插槽</p> </template> // 作用域插槽 <template> <el-form> <el-form-item> <el-link>{{ current.id }}</el-link> </el-form-item> <el-form-item> <el-link>{{ current.name }}</el-link> </el-form-item> <el-form-item> <el-link>{{ current.label }}</el-link> </el-form-item> <el-form-item> <el-link>{{ current.group }}</el-link> </el-form-item> <el-form-item> <el-link>{{ current.runtime }}</el-link> </el-form-item> <el-form-item> <el-link>{{ current.category }}</el-link> </el-form-item> </el-form> </template> </test> //==============vue3の定番テクニックとvue2との違いを整理して共有(一部)使用插槽//在vue3の定番テクニックとvue2との違いを整理して共有(一部)中,插槽使用v-slot 简写用#<p> <slot></slot> <slot></slot></p><helloworld> <template> // 可以写为v-slot:default #后面跟的是插槽名称 <p>默认插槽</p> </template> //作用域插槽 <template> // 可以写为v-slot:test="newData" <p>{{ newData.aa }}</p> <p>{{ newData.bb }}</p> </template></helloworld>//一个组件里面具有多个插槽时,一定要带上名称,否则可能会导致作用域错乱
// 注册一个全局自定义指令 `v-focus`Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() }})Vue 2 では、カスタマイズ ディレクティブは次のとおりです。次のオプションのフックを通じて作成されます:
Vue 3 では、カスタム命令の API がよりセマンティックになるように変更されました。コンポーネントのライフサイクルの変更と同様に、これもすべてセマンティックを改善するためです。変更点は次のとおりです:bind: ディレクティブが最初に要素にバインドされるときに 1 回だけ呼び出されます。ここではワンタイムの初期化設定を行うことができます。
- inserted: バインドされた要素が親ノードに挿入されるときに呼び出されます (親ノードのみが存在することが保証されますが、ドキュメントに挿入されていない可能性があります)。
- update: コンポーネントの VNode が更新されるときに呼び出されますが、子 VNode が更新される前に発生する場合もあります。ディレクティブの値は変更されている場合もあれば、変更されていない場合もあります。ただし、更新前後の値を比較することで、不要なテンプレートの更新を無視できます (フック関数のパラメーターの詳細については、以下を参照してください)。
- componentUpdated: 命令が配置されているコンポーネントのすべての VNode とそのサブ VNode が更新された後に呼び出されます。
- unbind: 命令が要素からバインドされていないときに、1 回だけ呼び出されます。
const { createApp } from "vue"const app = createApp({})app.directive('focus', { mounted(el) { el.focus() }})次に、次のように、テンプレート内の任意の要素で新しい v-focus ディレクティブを使用できます。 :
<input>
变更:在自定义组件上使用v-model时, 属性以及事件的默认名称变了 变更:v-bind的.sync修饰符在 Vue 3 中又被去掉了, 合并到了v-model里 新增:同一组件可以同时设置多个 v-model 新增:开发者可以自定义 v-model修饰符それについてさらに詳しく学びましょう。コンポーネントの v-model を使用して vue2 と vue3 を比較します。
例:
vue2 の入力ボックスの双方向バインディングは、実際には value 属性を渡して入力イベントをトリガーすることと同等です:
<input><input> <input><input>現時点では、v-model はコンポーネントの value 属性にのみバインドできます。コンポーネントに別の属性を使用したい場合、および入力をトリガーして値を更新したくない場合。
但是在实际开发中,有些场景我们可能需要对一个 prop 进行 “双向绑定”, 这里以最常见的 dialog 为例子:dialog 挺合适属性双向绑定的, 外部可以控制组件的visible显示或者隐藏,组件内部关闭可以控制 visible属性隐藏,同时 visible 属性同步传输到外部。组件内部, 当我们关闭dialog时, 在子组件中以 update:PropName 模式触发事件。イベントは
this.$emit('update:visible', false)です。その後、データ更新のために親コンポーネントでこのイベントをリッスンできます。
<el-dialog></el-dialog>vue2 の開発では、実際に新しいもの
sync なので、実装を簡素化するために
v-bind.sync を使用することもできます:
<el-dialog></el-dialog>上記の
v-model Vue2 での実装とコンポーネント プロパティの双方向バインディングですが、Vue 3 ではどのように実装する必要がありますか?
Vue3 では、カスタム コンポーネントで v-model を使用することは、
modelValue 属性を渡して
update:modelValue イベントをトリガーすることと同じです。属性名をバインドしたい場合は、1 つのパラメーターを
v-model
v-model をバインドできます:
<el-dialog></el-dialog> <el-dialog></el-dialog>
この書き方 .sync などというものは全くなく、Vue 3 では .sync の書き方を放棄し、一律 v-model を使用しました。
7. 非同期コンポーネントの使用Vue3 で defineAsyncComponent を使用して非同期コンポーネントを定義します。設定オプション コンポーネントはローダーに置き換えられます。ローダー関数自体は解決パラメーターと拒否パラメーターを受け取らなくなり、 <el-dialog></el-dialog><el-dialog></el-dialog>
<template> <!-- 异步组件的使用 --> <asyncpage></asyncpage><script>import { defineAsyncComponent } from "vue";export default { components: { // 无配置项异步组件 AsyncPage: defineAsyncComponent(() => import("./NextPage.vue")), // 有配置项异步组件 AsyncPageWithOptions: defineAsyncComponent({ loader: () => import("./NextPage.vue"), delay: 200, timeout: 3000, errorComponent: () => import("./ErrorComponent.vue"), loadingComponent: () => import("./LoadingComponent.vue"), }) },}</script></template>について知りたい場合は、Promise を返します。
糖衣構文、ここに移動してください vue3 セットアップ糖衣構文 (部分的な概要) まず、Composition が持つ API を見てみましょう
使用Composition API 解决我们在完成功能时,在 data、methods、computed 以及 mounted 中反复的跳转,他将零散分布的 逻辑组合在一起维护,并可以将单独的逻辑再分为单独的文件次の出力が表示されます:
setup の実行タイミングは
より前です。詳細は後述のライフサイクル説明を参照してください。 セットアップ パラメータ
- props: 组件传入的属性
- context
setup
中接受的props
是响应式的, 当传入新的 props
时,会及时被更新。
由于是响应式的, 所以不可以使用 ES6 解构,解构会消除它的响应式。
错误代码示例, 这段代码会让 props
不再支持响应式:
setup(props) { const { name } = props; console.log(name); const state = reactive({ count: 0 }); return { state, }; },
对于以上的的问题,我们可以在后面的toRefs进行解释。
现在我们就来讲一下:
在 vue2.x 中, 定义数据都是在data
中。
但是 Vue3.x 可以使用reactive
和ref
来进行数据定义。
那么ref和reactive他们有什么区别呢?
reactive用于处理对象的双向绑定,ref处理 js 基础类型或者处理对象的双向绑定。 注意refs 它接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property.value。
<template> <p> </p> <p>计数:{{ num }}s</p> <p>主人年龄:{{ person.age }}</p> <p>主人姓名:{{ person.name }}</p> <p>动物类别:{{ animal.type }}</p> <p>动物名称:{{ animal.name }}</p> <p>动物年龄:{{ animal.age }}</p> </template><script>import { defineComponent, reactive, ref } from "vue";export default defineComponent({ setup() { //使用ref声明基本类型 const num = ref(0); //使用ref声明对象 const person = ref({ age: 20, name: "张三" }); //使用reactive声明对象 const animal = reactive({ type: "猫", name: "小花", age: 5 }); setTimeout(() => { person.value.age = person.value.age + 1; person.value.name = "李四"; animal.age++; }, 1000); setInterval(() => { num.value++; }, 1000); return { num, animal, person, }; },});</script>
我们绑定到页面是通过user.name,user.age
;这样写感觉很繁琐,我们能不能直接将user中的属性解构出来使用呢?
答案是不能直接对user
进行结构, 这样会消除它的响应式, 这里就和上面我们说props不能使用 ES6 直接解构就呼应上了。
那我们就想使用解构后的数据怎么办,解决办法就是使用toRefs
。toRefs
用于将一个 reactive
对象转化为属性全部为 ref
对象的普通对象。具体使用方式如下:
<template> <p> </p> <p>计数:{{ num }}s</p> <p>主人年龄:{{ person.age }}</p> <p>主人姓名:{{ person.name }}</p> <p>动物类别:{{ atype }}</p> <p>动物名称:{{ aname }}</p> <p>动物年龄:{{ aage }}</p> </template><script>import { defineComponent, reactive, ref, toRefs } from "vue";export default defineComponent({ setup() { //使用ref声明基本类型 const num = ref(0); //使用ref声明对象 const person = ref({ age: 20, name: "张三" }); //使用reactive声明对象 const animal = reactive({ atype: "猫", aname: "小花", aage: 5 }); setTimeout(() => { person.value.age = person.value.age + 1; person.value.name = "李四"; animal.aage++; }, 1000); setInterval(() => { num.value++; }, 1000); return { num, person, ...toRefs(animal), }; },});</script>
有时我们想跟踪响应式对象 (ref 或 reactive)
的变化,但我们也希望防止在应用程序的某个位置更改它,这时候,我们就需要readonly
。
例如,当我们有一个被传递的响应式对象时,我们不想让它在传递的的时候被改变。为此,我们可以基于原始对象创建一个只读的 proxy
对象:
import { reactive, readonly } from 'vue' const original = reactive({ count: 0 }) const copy = readonly(original) // 通过 original 修改 count,将会触发依赖 copy 的侦听器 original.count++ // 通过 copy 修改 count,将导致失败并出现警告 copy.count++ // 警告: "Set operation on key 'count' failed: target is readonly."
在最开始的时候,我们就看到了两张图,其中的变化我们可以总结一下
我们可以看到beforeCreate
和created
被setup
替换了(但是 Vue3 中你仍然可以使用, 因为 Vue3 是向下兼容的, 也就是你实际使用的是 vue2 的)。
其次,钩子命名都增加了on; Vue3.x 还新增用于调试的钩子函数onRenderTriggered
和onRenderTricked
下面我们简单使用几个钩子, 方便大家学习如何使用,Vue3.x 中的钩子是需要从 vue 中导入的:
import { defineComponent, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked, onRenderTriggered,} from "vue";export default defineComponent({ //beforeCreate和created是vue2的 beforeCreate() { console.log("------beforeCreate-----"); }, created() { console.log("------created-----"); }, setup() { console.log("------setup-----"); // vue3.xvue3の定番テクニックとvue2との違いを整理して共有(一部)写在setup中 onBeforeMount(() => { console.log("------onBeforeMount-----"); }); onMounted(() => { console.log("------onMounted-----"); }); onBeforeUpdate(() => { console.log("------onBeforeUpdate-----"); }); onUpdated(() => { console.log("------onUpdated-----"); }); onBeforeUnmount(() => { console.log("------onBeforeUnmount-----"); }); onUnmounted(() => { console.log("------onUnmounted-----"); }); onErrorCaptured(() => { console.log("------onErrorCaptured-----"); }); onRenderTracked(() => { console.log("------onRenderTracked-----"); }); // 调试哪些数据发生了变化 onRenderTriggered((event) => { console.log("------onRenderTriggered-----", event); }); },});
具体怎么使用,是干什么的请参考官方文档,这里就不一一赘述了。
watch
函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。
watch(source, callback, [options])
参数说明:
- source: 可以支持 string,Object,Function,Array;
- 用于指定要侦听的响应式变量 callback:
- 执行的回调函数 options:支持 deep、immediate 和 flush 选项。
其实整体和原来的vue3の定番テクニックとvue2との違いを整理して共有(一部)有一定的相似性,基本参数没有发生大的改变。
接下来我会分别介绍这个三个参数都是如何使用的, 如果你对 watch 的使用不明白的请往下看:
//监听reactive对象:watch( () => animal.aage, (curAge, preAge) => { console.log("新值:", curAge, "老值:", preAge); } );//监听ref变量 watch(num, (newVal, oldVal) => { console.log("新值:", newVal, "老值:", oldVal); }); //多个值的监听 watch([() => animal.aage, num], ([curAge, newVal], [preAge, oldVal]) => { console.log("新值:", curAge, "老值:", preAge); console.log("新值:", newVal, "老值:", oldVal); }); //监听对象复杂时,请使用深度监听 让函数的第三个参数为deep:truewatch( () => state.animal, (newType, oldType) => { console.log("新值:", newType, "老值:", oldType); }, { deep: true } );
默认情况下,watch
是惰性的, 那什么情况下不是惰性的, 可以立即执行回调函数呢?其实使用也很简单, 给第三个参数中设置immediate: true
即可。
//停止监听函数 const stopWatchRoom = watch( () => state.animal, (newType, oldType) => { console.log("新值:", newType, "老值:", oldType); }, { deep: true } ); setTimeout(() => { // 停止监听 stopWatchRoom(); }, 3000);
还有一个监听函数watchEffect
,介绍一下watchEffect
,看看它的使用和watch
究竟有何不同,在上面代码的基础上,我们来编写。
watchEffect(() => { console.log(num); });
执行结果首先打印一次num
值;然后每隔一秒,打印num
值。
从上面的代码可以看出, 并没有像watch一样需要先传入依赖,watchEffect会自动收集依赖, 只要指定一个回调函数。在组件初始化时, 会先执行一次来收集依赖, 然后当收集到的依赖中数据发生变化时, 就会再次执行回调函数。所以总结对比如下:
- watchEffect 不需要手动传入依赖
- watchEffect 会先执行一次用来自动收集依赖
- watchEffect无法获取到变化前的值, 只能获取变化后的值
在之前vue用的mixin
,所谓的混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
现在的vue3の定番テクニックとvue2との違いを整理して共有(一部)提供了一种新的东西 vue-hooks
。具体的vue-hooks
,请参考网上教程
为什么产生了hooks
?
首先从class-component/vue-options
说起:
- 跨组件代码难以复用
- 大组件,维护困难,颗粒度不好控制,细粒度划分时,组件嵌套存层次太深影响性能
- 类组件,this不可控,逻辑分散,不容易理解
- mixins具有副作用,逻辑互相嵌套,数据来源不明,且不能互相消费
当一个模版依赖了很多mixin
的时候,很容易出现数据来源不清或者命名冲突的问题,而且开发mixins
的时候,逻辑及逻辑依赖的属性互相分散且mixin
之间不可互相消费。这些都是开发中令人非常痛苦的点。
hooks存在以下优势:
- 允许hooks间相互传递值
- 组件之间重用状态逻辑
- 明确指出逻辑来自哪里
我们先来封装一个hooks,假如这个hooks是一个实现年龄加减,获取双倍年龄的函数。用单独的文件存储 bus/useAge.ts
import { ref, Ref, computed } from "vue";type CountResultProps = { age: Ref<number>; doubleAge: Ref<number>; increase: (curAge?: number) => void; decrease: (curAge?: number) => void;};export default function useCount(initValue = 20): CountResultProps { const age = ref(initValue); const increase = (curAge?: number): void => { if (typeof curAge !== "undefined") { age.value += curAge; } else { age.value += 1; } }; const doubleAge = computed(() => age.value * 2); const decrease = (curAge?: number): void => { if (typeof curAge !== "undefined") { age.value -= curAge; } else { age.value -= 1; } }; return { age, doubleAge, increase, decrease, };}</number></number>
在组件里面调用该hooks
<template> <p> </p> <p>计数:{{ num }}s</p> <p>主人年龄:{{ person.age }}</p> <p>主人姓名:{{ person.name }}</p> <p>动物类别:{{ atype }}</p> <p>动物名称:{{ aname }}</p> <p>动物年龄:{{ aage }}</p> <p>count: {{ age }}</p> <p>双倍年龄: {{ doubleAge }}</p> <p> <button>加1</button> <button>减一</button> </p> </template><script>import { defineComponent, reactive, ref, toRefs, watch, watchEffect,} from "vue";import useAge from "../bus/useAge.ts";export default defineComponent({ setup() { //使用ref声明基本类型 const num = ref(0); //使用ref声明对象 const person = ref({ age: 20, name: "张三" }); //使用reactive声明对象 const animal = reactive({ atype: "猫", aname: "小花", aage: 5 }); setTimeout(() => { person.value.age = person.value.age + 1; person.value.name = "李四"; animal.aage++; animal.aname = "小橘"; }, 1000); setInterval(() => { num.value++; }, 1000); const { age, doubleAge, increase, decrease } = useAge(22); return { num, person, ...toRefs(animal), age, doubleAge, increase, decrease, }; },});</script>
在vue3の定番テクニックとvue2との違いを整理して共有(一部)中,应该很多人都使用了$set
这个东西吧。
数据更新了,页面为什么不变化呢?什么时候我们用$forceUpdate
强制更新呢?
在vue2.x中,实现数据监听使用的是Object.defineProperty
。而vue3.x使用的是Proxy
Object.defineProperty
只能劫持对象的属性, 而 Proxy
是直接代理对象由于
Object.defineProperty
只能劫持对象属性,需要遍历对象的每一个属性,如果属性值也是对象,就需要递归进行深度遍历。
但是Proxy
直接代理对象, 不需要遍历操作
Object.defineProperty
对新增属性需要手动进行Observe
因为
Object.defineProperty
劫持的是对象的属性,所以新增属性时,需要重新遍历对象,
对其新增属性再次使用Object.defineProperty
进行劫持。也就是 Vue2.x
中给数组和对象新增属性时,需要使用$set
才能保证新增的属性也是响应式的,
$set内部也是通过调用Object.defineProperty
去处理的。
Proxy
有多种拦截方法,如apply,deleteProperty
等等,是Object.defineProperty()
不具备的。Proxy
是返回值是一个对象,可以直接进行操作,而defineProperty()
要先遍历所有对象属性值才能进行操作。Object.defineProperty()
兼容性高一些。Teleport
是 Vue3.x 新推出的功能
Teleport
是什么呢?
Teleport
就像是哆啦 A 梦中的「任意门」,任意门的作用就是可以将人瞬间传送到另一个地方。有了这个认识,我们再来看一下为什么需要用到 Teleport
的特性呢,看一个小例子:
例如我们在使用
Dialog
组件时,我们实际开发中经常会使用到Dialog
,此时Dialog
就被渲染到一层层子组件内部,处理嵌套组件的定位、z-index
和样式都变得困难。但是组件希望位于页面的最上方,这时候我们将Dialog
组件挂载在body
上面是最好控制的,我们能够很好的通过zIndex来控制Dialog
的位置,当他嵌套在templat里面的时候就不那么容易了。简单来说就是,即希望继续在组件内部使用Dialog
,又希望渲染的DOM
结构不嵌套在组件内部的DOM
中。
此时就需要 Teleport
上场,我们可以用<teleport></teleport>
包裹Dialog
, 此时就建立了一个传送门,可以将Dialog
渲染的内容传送到任何指定的地方。
<template> <p> </p> <p>计数:{{ num }}s</p> <p>主人年龄:{{ person.age }}</p> <p>主人姓名:{{ person.name }}</p> <p>动物类别:{{ atype }}</p> <p>动物名称:{{ aname }}</p> <p>动物年龄:{{ aage }}</p> <p>count: {{ age }}</p> <p>倍数: {{ doubleAge }}</p> <p> <button>加1</button> <button>减一</button> </p> <el-button>点击打开 Dialog</el-button> > <teleport> <el-dialog> <span>这是一段信息</span> <template> <span> <el-button>取 消</el-button> <el-button>确 定</el-button> > </span> </template> </el-dialog> </teleport> </template><script>import { defineComponent, reactive, ref, toRefs,} from "vue";export default defineComponent({ setup() { //使用ref声明基本类型 const num = ref(0); const dialogVisible = ref(false); //使用ref声明对象 const person = ref({ age: 20, name: "张三" }); //使用reactive声明对象 const animal = reactive({ atype: "猫", aname: "小花", aage: 5 }); setTimeout(() => { person.value.age = person.value.age + 1; person.value.name = "李四"; animal.aage++; animal.aname = "小橘"; }, 1000); setInterval(() => { num.value++; }, 1000); return { dialogVisible, num, person, ...toRefs(animal), }; },});</script>
我们可以很清楚的看到teleport上有一个to属性,这个属性是讲当前节点传送到制定位置去的。位置应该传送到哪里呢?
答案就是在index.html上面
下面是我们的首页 你会看到有一个p的ID名为dialogLL,teleport就将节点挂载在这里来了
nbsp;html> <meta> <link> <meta> <title>Vite App</title> <p></p> <p></p> <script></script>
如图所示:
Suspense
是 Vue3.x 中新增的特性, 那它有什么用呢?我们通过 Vue2.x 中的一些场景来认识它的作用。 Vue2.x 中应该经常遇到这样的场景:
<template> <p> </p> <p>...</p> <p>加载中...</p> </template>
在前后端交互获取数据时, 是一个异步过程,一般我们都会提供一个加载中的动画,当数据返回时配合v-if
来控制数据显示。
它提供两个template slot
, 刚开始会渲染一个 fallback
状态下的内容, 直到到达某个条件后才会渲染 default
状态的正式内容, 通过使用Suspense
组件进行展示异步渲染就更加的简单。
具体的使用,我们可以用下面的例子来表示:
这是需要等待取值完成的的组件:
<template> <h1>{{ getData.result }}</h1></template><script>export default { name: "NewModel", async setup() { let getData = await new Promise((resolve) => { setTimeout(() => { return resolve({ result: "OK" }); }, 3000); }); return { getData, }; },};</script>
在其他组件内调用它,当等待取值的组件取值完成后,会将loading状态变为OK状态
<template> <p> <suspense> <template> <newsuspense></newsuspense> </template> <template> <h1>Loadding...</h1> </template> </suspense> </p></template><script>import NewSuspense from "./suspens.vue";export default { name: "AppMain", components: { NewSuspense, },};</script><style></style>
效果如图:
在 Vue2.x 中, template
中只允许有一个根节点:
<template> <p> <span></span> <span></span> </p></template>
但是在 Vue3.x 中,你可以直接写多个根节点:
<template> <span></span> <span></span></template>
Vue3.x 在考虑到 tree-shaking
的基础上重构了全局和内部 API, 表现结果就是现在的全局 API 需要通过 ES Module
的引用方式进行具名引用, 比如在 Vue2.x 中,我们要使用 nextTick
:
// vue2.ximport Vue from "vue"Vue.nextTick(()=>{ ...})或者 this.nextTick(()=>{ ...})
Vue.nextTick()
是一个从 Vue 对象直接暴露出来的全局 API,其实 $nextTick()
只是 Vue.nextTick()
的一个简易包装,只是为了方便而把后者的回调函数的 this 绑定到了当前的实例。
在 Vue3.x 中改写成这样:
import { nextTick } from "vue"nextTick(() =>{ ...})
受影响的 API
这是一个比较大的变化, 因为以前的全局 API 现在只能通过具名导入,这一更改会对以下 API 有影响:
- Vue.nextTick
- Vue.observable(用 Vue.reactive 替换)
- Vue.version
- Vue.compile(仅限完整版本时可用)
- Vue.set(仅在 2.x 兼容版本中可用)
- Vue.delete(与上同)
相关推荐:vue.js视频教程
以上がvue3の定番テクニックとvue2との違いを整理して共有(一部)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。