vue3の定番テクニックとvue2との違いを整理して共有(一部)

WBOY
リリース: 2022-01-31 06:00:31
転載
3957 人が閲覧しました

この記事では、ライフサイクルの変更、インスタンスの変更、メソッドの変更など、vue3 と vue2 の違いについての知識を提供します。皆様のお役に立てれば幸いです。

vue3の定番テクニックとvue2との違いを整理して共有(一部)

1. ライフサイクルの変更: 3.x (上位) 2.x (下位)

vue3の定番テクニックとvue2との違いを整理して共有(一部)
vue3の定番テクニックとvue2との違いを整理して共有(一部)

vue3の定番テクニックとvue2との違いを整理して共有(一部) と vue3の定番テクニックとvue2との違いを整理して共有(一部) の間のライフサイクル関数が破棄されたときに変更されたことを確認するのは難しくありません:

beforeDestroy --> beforeUnmount
destroyed --> unmounted
ログイン後にコピー
其他的区别主要在于书写使用的语言上的差别
在ts中使用 class 类组件书写可以 参考 vue-class-component 或者 vue-property-decorator
书写的风格和vue3の定番テクニックとvue2との違いを整理して共有(一部)的选项式区别不大。
如果使用js书写代码 则应当使用组合式。
ログイン後にコピー

特定の変更によって引き起こされる問題は、次の組み合わせになります。書き方を解説。

2. グローバル変数の定義方法の変更

// 之前(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'
ログイン後にコピー

3. vue インスタンス作成の変更

//=======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')
ログイン後にコピー

4. の変更スロットの使用法##
//================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>//一个组件里面具有多个插槽时,一定要带上名称,否则可能会导致作用域错乱
ログイン後にコピー

5. カスタム命令

Vue 2 でカスタム命令を実装します:

// 注册一个全局自定义指令 `v-focus`Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }})
ログイン後にコピー
Vue 2 では、カスタマイズ ディレクティブは次のとおりです。次のオプションのフックを通じて作成されます:

    bind: ディレクティブが最初に要素にバインドされるときに 1 回だけ呼び出されます。ここではワンタイムの初期化設定を行うことができます。
  • inserted: バインドされた要素が親ノードに挿入されるときに呼び出されます (親ノードのみが存在することが保証されますが、ドキュメントに挿入されていない可能性があります)。
  • update: コンポーネントの VNode が更新されるときに呼び出されますが、子 VNode が更新される前に発生する場合もあります。ディレクティブの値は変更されている場合もあれば、変更されていない場合もあります。ただし、更新前後の値を比較することで、不要なテンプレートの更新を無視できます (フック関数のパラメーターの詳細については、以下を参照してください)。
  • componentUpdated: 命令が配置されているコンポーネントのすべての VNode とそのサブ VNode が更新された後に呼び出されます。
  • unbind: 命令が要素からバインドされていないときに、1 回だけ呼び出されます。
Vue 3 では、カスタム命令の API がよりセマンティックになるように変更されました。コンポーネントのライフサイクルの変更と同様に、これもすべてセマンティックを改善するためです。変更点は次のとおりです:


vue3の定番テクニックとvue2との違いを整理して共有(一部)

Vue3 では、次のようにディレクティブをカスタマイズできます:

const { createApp } from "vue"const app = createApp({})app.directive('focus', {
    mounted(el) {
        el.focus()
    }})
ログイン後にコピー
次に、次のように、テンプレート内の任意の要素で新しい v-focus ディレクティブを使用できます。 :

<input>
ログイン後にコピー

6.v-model upgrade

V-model は Vue 3 で大幅な変更を受けました:

变更:在自定义组件上使用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>
ログイン後にコピー

8.Composition API

<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 を見てみましょう


vue3の定番テクニックとvue2との違いを整理して共有(一部)

##setup
  • #setup は Vue3.x の新しいオプションで、コンポーネント内の Comboposition API への入り口です。
  • セットアップ実行タイミング
コードの一部を通じて知ることができます:

   使用Composition API 解决我们在完成功能时,在 data、methods、computed 以及 mounted 中反复的跳转,他将零散分布的
   逻辑组合在一起维护,并可以将单独的逻辑再分为单独的文件
ログイン後にコピー
次の出力が表示されます:



setupvue3の定番テクニックとvue2との違いを整理して共有(一部) の実行タイミングは

beforeCreate

より前です。詳細は後述のライフサイクル説明を参照してください。 セットアップ パラメータ

  1. セットアップを使用する場合、次の 2 つのパラメータを受け入れます:
    • props: 组件传入的属性
    • context

    setup 中接受的props是响应式的, 当传入新的 props 时,会及时被更新。
    由于是响应式的, 所以不可以使用 ES6 解构,解构会消除它的响应式。
    错误代码示例, 这段代码会让 props 不再支持响应式:

    setup(props) {
        const { name } = props;
        console.log(name);
        const state = reactive({ count: 0 });
        return {
          state,
        };
      },
    ログイン後にコピー

    对于以上的的问题,我们可以在后面的toRefs进行解释。
    现在我们就来讲一下:

    1. reactive、ref、toRefs、readonly

    在 vue2.x 中, 定义数据都是在data中。
    但是 Vue3.x 可以使用reactiveref来进行数据定义。
    那么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."
    ログイン後にコピー
    • vue3の定番テクニックとvue2との違いを整理して共有(一部)钩子

    在最开始的时候,我们就看到了两张图,其中的变化我们可以总结一下

    vue3の定番テクニックとvue2との違いを整理して共有(一部)

    我们可以看到beforeCreatecreatedsetup替换了(但是 Vue3 中你仍然可以使用, 因为 Vue3 是向下兼容的, 也就是你实际使用的是 vue2 的)。
    其次,钩子命名都增加了on; Vue3.x 还新增用于调试的钩子函数onRenderTriggeredonRenderTricked
    下面我们简单使用几个钩子, 方便大家学习如何使用,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 与 watchEffect 的用法

    watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。

    watch(source, callback, [options])
    ログイン後にコピー

    参数说明:

    1. source: 可以支持 string,Object,Function,Array;
    2. 用于指定要侦听的响应式变量 callback:
    3. 执行的回调函数 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无法获取到变化前的值, 只能获取变化后的值

    9.Hooks

    在之前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>
    ログイン後にコピー

    10.vue2.x 与vue3.x的响应式数据对比

    在vue3の定番テクニックとvue2との違いを整理して共有(一部)中,应该很多人都使用了$set这个东西吧。
    数据更新了,页面为什么不变化呢?什么时候我们用$forceUpdate强制更新呢?
    在vue2.x中,实现数据监听使用的是Object.defineProperty。而vue3.x使用的是Proxy

    1. Object.defineProperty只能劫持对象的属性, 而 Proxy 是直接代理对象

    由于Object.defineProperty只能劫持对象属性,需要遍历对象的每一个属性,如果属性值也是对象,就需要递归进行深度遍历。
    但是Proxy 直接代理对象, 不需要遍历操作

    1. Object.defineProperty对新增属性需要手动进行Observe

    因为Object.defineProperty劫持的是对象的属性,所以新增属性时,需要重新遍历对象,
    对其新增属性再次使用Object.defineProperty进行劫持。也就是 Vue2.x
    中给数组和对象新增属性时,需要使用$set才能保证新增的属性也是响应式的,
    $set内部也是通过调用Object.defineProperty去处理的。

    1. Proxy有多种拦截方法,如apply,deleteProperty等等,是Object.defineProperty()不具备的。
    2. Proxy是返回值是一个对象,可以直接进行操作,而defineProperty()要先遍历所有对象属性值才能进行操作。
      但是相对来说,Object.defineProperty()兼容性高一些。

    11.Teleport

    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>
      
    ログイン後にコピー

    如图所示:
    vue3の定番テクニックとvue2との違いを整理して共有(一部)

    12.Suspense

    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>
    ログイン後にコピー

    效果如图:
    vue3の定番テクニックとvue2との違いを整理して共有(一部)

    13.片段(Fragment)

    在 Vue2.x 中, template中只允许有一个根节点:

    <template>
        <p>
            <span></span>
            <span></span>
        </p></template>
    ログイン後にコピー

    但是在 Vue3.x 中,你可以直接写多个根节点:

    <template>
        <span></span>
        <span></span></template>
    ログイン後にコピー

    14.Tree-Shaking变化

    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 有影响:

    1. Vue.nextTick
    2. Vue.observable(用 Vue.reactive 替换)
    3. Vue.version
    4. Vue.compile(仅限完整版本时可用)
    5. Vue.set(仅在 2.x 兼容版本中可用)
    6. Vue.delete(与上同)

    相关推荐:vue.js视频教程

以上がvue3の定番テクニックとvue2との違いを整理して共有(一部)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
vue
ソース:csdn.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!