vue3.0とvue2.0の比較

序文:

            vue3.0を1回整理する

目次:

1.vue3.0のハイライト

1.パフォーマンスはvue2.xより1.2〜2倍高速です

2.オンデマンドコンパイル、オンデマンドインポート、vue2.xよりも少ないボリュームをサポートします

3. ReactHooksと同様の複合APIをサポートします

4. tsによって書かれたため、tsのサポートが向上しました

5.カスタムレンダリング用のAPIが公開されています

6.より高度なコンポーネントを提供

2.vue3.0はどのように高速になりますか

1.diffメソッドの最適化

2.静的プロモーション

3.イベントリスナーキャッシュ

4.ssrレンダリング

3.vue3.0を作成する3つの方法

1.CLIビュー

2.Webpack

3.クイック

1)Viteをインストールします

2)Viteを使用してVue3.0プロジェクトを作成します

4. Viteとは何ですか?ここでViteを使用する場合は、これを使用してプロジェクトを作成し、他のユーザーはアップグレードコマンドを直接実行できます。

1.viteをインストールします

2.viteを使用してvue3.0プロジェクトを作成します

3.プロジェクトをインストールして実行します

5.組み合わせAPI

1.ref()

2.reactive()関数

3.コンポジションAPIとオプションAPIの混合使用

4.セットアップ機能の実行タイミングと注意点

5.再帰的監視

6.toRaw()元のデータは変更されますが、UIは更新されません

7.markRaw()は元のデータを確認し、追跡されることはありません

8. toRef()、toRefおよびref、toRefおよびtoRefs

9.customRef()カスタム参照


1.vue3.0のハイライト

1.パフォーマンスはvue2.xより1.2〜2倍高速です

①diff方法优化
②静态提升
③事件侦听器缓存
④ssr渲染

2.オンデマンドコンパイル、オンデマンドインポート、vue2.xよりも少ないボリュームをサポートします

3. ReactHooksと同様の複合APIをサポートします

4. tsによって書かれたため、tsのサポートが向上しました

5.カスタムレンダリング用のAPIが公開されています

6.より高度なコンポーネントを提供

2.vue3.0はどのように高速になりますか

1.diffメソッドの最適化

  • vue2.0の仮想DOMは完全な比較用です
  • Vue3.0は、新しい静的フラグ(PatchFlag)を追加します。これは、前回仮想ノードを比較するときに、パッチフラグのあるノードのみが比較されるというものです。そして、比較される現在のノードの特定の内容は、フラグの情報を通じて知ることができます。
  • ここに画像の説明を挿入
    検証:静的タグ
    vue3.0変換コードのURLを追加するかどうか:https:// https://vue-next-template-explorer.netlify.app/
    ここに画像の説明を挿入
    静的タグ列挙クラス:
    ここに画像の説明を挿入

2.静的プロモーション

  • 要素が更新に参加しているかどうかに関係なく、vue2.0は毎回再作成され、レンダリングされます
  • 更新に参加しない要素の場合、vue3.0は静的プロモーションを実行します。これは一度だけ新しく作成され、レンダリング中に直接再利用できます。
  •  

検証:
デフォルトでは、createNodeノードは毎回再作成されます。ここではhoisStaticを選択します。
これらのノードがレンダーから抽出され、グローバル変数になることがわかります。後でレンダリングするたびに再利用できます
ここに画像の説明を挿入

3.イベントリスナーキャッシュ

  • デフォルトでは、onClickは動的バインディングと見なされるため、毎回その変更を追跡します。ただし、イベントにバインドされた関数は同じ関数(同じメソッド)であるため、追跡の変更はなく、キャッシュして再利用するだけです。
    検証:
    [注]変換されたコードを理解できない場合がありますが、問題ではありません。Vue3のdiffアルゴリズムでは、静的マークがあるかどうかだけを観察する必要があるため、静的マークがあるものだけが比較および追跡されます。
//事件监听缓存
<button @click="onClick">按钮</button>
//开启事件监听缓存之前(把静态提升关闭了也是这样)
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", { onClick: _ctx.onClick }, "按钮", 8 /* PROPS */, ["onClick"])
  ]))
}
//开启事件监听缓存之后(把options选择为cacheHandlers)
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("button", {
      onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args)))
    }, "按钮")
  ]))
}

4.ssrレンダリング

  • 静的コンテンツが大量にある場合、これらのコンテンツは純粋な文字列としてバッファにプッシュされます。動的バインディングがある場合でも、テンプレート補間によって埋め込まれます。これは、仮想domを介したレンダリングよりもはるかに高速です。
  • 静的コンテンツが特定のレベルに達すると、_createStaticVNodeメソッドを使用して、クライアント側で静的ノードが生成されます。これらの静的ノードは、オブジェクトを作成せずに直接innerHtmlになり、オブジェクトに従ってレンダリングされます。

3.vue3.0を作成する3つの方法

1.CLIビュー

  • git clone https://github.com/vue.js/vue-next-webpack-preview.git ProjectName
  • cd ProjectName
  • npmインストール
  • npm run dev

2.Webpack

  • npm install -g @ vue / cli
  • vue create ProjectName
  • cd ProjectName
  • vue addvue-next
  • npm runserve

3.クイック

1)Viteをインストールします

npm install -g create-vite-app

2)Viteを使用してVue3.0プロジェクトを作成します

create-vite-app projectName

[注]このコマンドを使用するとエラーが発生しました。もちろん、すべての人がこの状況に遭遇したわけではありません。エラーを報告しない場合は、エラーを解決する必要はありません。
その時、たくさんの情報をチェックしましたが、nodejsのバージョンが低すぎてアップグレードが必要だという人もいました。最初は、効果がないようにアップグレードしました。
解決策:設定nodejs環境変数
で①プログラムファイル\ cが\ nodejsファイルフォルダの作成node_cachenode_global 2つのフォルダ
ここに画像の説明を挿入
に空のフォルダを作成した後、CMDコマンドウィンドウを開き、②2を、タイプ

npm config set prefix “C:\Program Files\nodejs\node_global”
npm config set cache “C:\Program Files\nodejs\node_cache”

③次に、環境変数を設定し、コマンドウィンドウを閉じます。「マイコンピュータ」-右クリック-「プロパティ」-「システムの詳細設定」-「詳細」-「環境変数」
④[システム変数]の下の環境変数ダイアログボックスに入ります。 ]新しい[NODE_PATH]を作成し、[C:\ Program Files \ nodejs \ node_global \ node_modules]と入力し、[User Variables]の下の[Path]を[C:\ Program Files \ nodejs \ node_global]
ここに画像の説明を挿入
変更します。最後に、黒を閉じます。ウィンドウを開いて再起動します次に、create-vite-app programNameコマンドを再試行して、エラーが報告されているかどうかを確認します。

3)依存する実行中のプロジェクトをインストールします

cd projectName
npm install
npm run dev

4. Viteとは何ですか?ここでViteを使用する場合は、これを使用してプロジェクトを作成し、他のユーザーはアップグレードコマンドを直接実行できます。

  • Viteは、Vueの作者がwebpackを置き換えるために開発したツールです。
  • 実装の原則は、es6インポートの機能を使用して、ファイルをロードするリクエストを送信し、これらのリクエストをインターセプトし、事前コンパイルを実行し、webpackの長いパッケージング時間を節約することです。

1.viteをインストールします

cnpm install -g create-vite-app

2.viteを使用してvue3.0プロジェクトを作成します

create -vite -app projectName

3.プロジェクトをインストールして実行します

cd projectName
npm install

5.組み合わせAPI

vue2.xの問題点:vue3.xの
組み合わせAPI:
セットアップ機能は組み合わせAPIの入力機能です

1.ref()

1)refとは何ですか?
      リアクティブと同様に、refもレスポンシブデータを実装するために使用される方法です。リアクティブはオブジェクトを渡す必要があるため、変数をレスポンシブにするだけの場合、エンタープライズ開発では非常に面倒になります。したがって、vue3には、単純な値を監視するためのrefメソッドが用意されています。

2)refの本質refの本質
     は実際には反応的です。ref関数に値を渡すと、ref関数の最下層が自動的にrefをeactiveに変換します(ref(10)—> react({value:18})など)。
注:
    ①データがtrefによって作成されている場合、vueが自動的に.valueを追加するため、テンプレートで使用するときに.valueを使用して取得する必要はありません。
    ②ただし、jsで使用するref関数はvalueから取得する必要があります。

3)参照関数と使用法
     関数:単純な型の変更のみを監視できます。
     使用法:インポートは{ref}を導入し、戻り値は公開します。refを取得するための変数には.valueが必要です

<script>
import {ref} from 'vue'
export default {
  name: 'App',
  setup(){
    let count=ref(0);

    function changeBtn(){
      count.value++;
    }
    return {count,changeBtn}
  }
}
</script>

2.reactive()関数

1)反応性とは何ですか?
      ①Reactiveは、vue3で提供さ
      れる応答データを実現する方法です。②vue2では、応答データはdefinePropertyを介して実現され、vue3では、応答データはes6のプロキシを介して実現されます。

2)
      リアクティブノート:リアクティブパラメータはオブジェクト(obj / json / arr)である必要があります
      ②他のオブジェクト(日付オブジェクトなど)がリアクティブに渡された場合、オブジェクトがデフォルトで変更されていると、インターフェイスは更新されません。更新するには、再割り当てすることで

3)関数と使用方法
      関数:オブジェクトと配列の変更を監視します。
       使用方法:importは{reactive}を導入し、returnはメソッド名を公開します。

<script>
import {ref} from 'vue'
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    let {state,remStu}=useRemoveStudent()
    return {state,remStu}
  }
}
//整个相关的方法和变量都写在一起了
  function useRemoveStudent(){
    let state=reactive({
      stus:[
        {id:1,name:'张三',age:10},
        {id:2,name:'李四',age:20},
        {id:3,name:'王五',age:30},
      ]
    });
    function remStu(index){
      state.stus=state.stus.filter((stu,idx)=>idx!==index);
    }
    return {state,remStu}
  }

</script>

複合APIのアイデア:
関連するメソッドと変数全体が一緒に記述されています

demo2:ユーザーの削除と追加

<template>
  <div>
    <form action="">
      <input type="text" v-model="state2.stu.id">
      <input type="text" v-model="state2.stu.name">
      <input type="text" v-model="state2.stu.age">
      <input type="submit" @click="addStu">
    </form>
    <ul>
      <li v-for="(stus,index) in state.stus" :key="stus.id"
      @click="remStu(index)">
        {
   
   {stus.name}}--{
   
   {stus.age}}
      </li>
    </ul>
  </div>
</template>

<script>
import {ref} from 'vue'
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    let {state,remStu}=useRemoveStudent()
    let {state2,addStu}=useAddStudent(state)
    return {state,remStu,state2,addStu}
  }
}
//删除用户
  function useRemoveStudent(){
    let state=reactive({
      stus:[
        {id:1,name:'张三',age:10},
        {id:2,name:'李四',age:20},
        {id:3,name:'王五',age:30},
      ]
    });
    function remStu(index){
      state.stus=state.stus.filter((stu,idx)=>idx!==index);
    }
    return {state,remStu}
  }
//增加用户
function useAddStudent(state){
  let state2=reactive({
    stu:{
      id:'',
      name:'',
      age:''
    }
  });
  function addStu(e){
    e.preventDefault();
    const stu=Object.assign({},state2.stu);
    state.stus.push(stu)
    state2.stu.id=''
    state2.stu.name=''
    state2.stu.age=''
  }
  return {state2,addStu}
}

</script>

[] ①refreactive
違い:           テンプレートでrefタイプのデータを使用する場合、vueは自動的に.valueを追加し          ます。テンプレートでreactiveデータを使用する場合、vueは自動的に.valueを追加しません。 。②vueは.valueを自動的に追加するかどうかをどのように決定しますか?         Vueは、データを解析する前に、データがrefタイプであるかどうかを自動的に判断します。         そうである場合は、自動的に.valueを追加し、そうでない場合は、.valueを自動的に追加しません。③現在のデータがref型かどうかをvueはどのように判断しますか?         現在のデータの__v_refによって判断されます。このプライベート属性があり、値がtrueの場合、それはデータのrefタイプを表します。④開発者は現在のデータ型をどのように判断しますか?         isRefとisReactiveは、それぞれ通常の関数とオブジェクトであるかどうかを判別します。








3.コンポジションAPIとオプションAPIの混合使用

オプションAPIは以前のvue2.xAPI
コンポジションAPはvue3.xの新しい構文になりました
コンポジションAPIとオプションAPIを混在させることができます。

コンポジションAPIの本質は何ですか?
複合API(またはインジェクションAPI)と翻訳できます。
その本質は、実行時にコンポジションAPIで公開されたデータをオプションAPIに注入することです。たとえば、共通の可変年齢が公開された場合、年齢が注入されます。 data()メソッドに移動します。メソッドsubmit()が公開され、このメソッドがメソッドに挿入されます。

4.セットアップ機能の実行タイミングと注意点

1)
     設定機能の実行タイミング:設定機能はbeforeCreateからcreatedまでの間に実行されます。
     beforeCreate:コンポーネントが作成されたばかりで、コンポーネントのデータとメソッドがまだ初期化されていないことを示します。created:コンポーネントが作成されたばかりで、コンポーネント
     のデータメソッドが初期化されていることを示します。

2)設定上の注意:
     ①設定機能実行時に作成したライフサイクルメソッドが実行されていないため、設定機能でデータやメソッドを使用することはできません。
     ②セットアップ関数ではデータやメソッドを使用できないため、Vueはセットアップ関数のこの値を直接Undefinedに変更し、誤用を防ぎます。
     ③セットアップ機能は同期のみ可能で、非同期はできません。

5.再帰的監視

1)再帰的監視
デフォルトでは、refまたはreactiveのどちらを使用するかは再帰的監視です

<template>
  <div>
    <p>{
   
   {state.a}}</p>
    <p>{
   
   {state.gf.b}}</p>
    <p>{
   
   {state.gf.f.c}}</p>
    <p>{
   
   {state.gf.f.s.d}}</p>
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {ref} from 'vue'
import {reactive} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=reactive({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.a='1';
      state.gf.b='2';
      state.gf.f.c='3';
      state.gf.f.s.d='4';
      console.log(state)
      console.log(state.gf)
      console.log(state.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

2)再帰的監視の問題
データ量が多いと、パフォーマンスが低下します。彼は各レイヤーをプロキシオブジェクトにラップしているからです。
ここに画像の説明を挿入

3)非再帰的監視
shadowRef / ShoulderReactive
非再帰的監視とは、最初のレイヤーのみを監視でき、他のレイヤーは監視できないことを意味します。
【使用シナリオ】監視が必要なデータ量が比較的多い場合にのみ使用します。
①浅い反応性

<script>
import {shallowReactive} from 'vue'
import {shallowRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowReactive({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.a='1';
      state.gf.b='2';
      state.gf.f.c='3';
      state.gf.f.s.d='4'
      console.log(state)
      console.log(state.gf)
      console.log(state.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

最初のレイヤーのみがプロキシとしてパッケージ化されていることがわかります

ここに画像の説明を挿入

shallowRefはshallowRefによってデータを作成する場合、Vueが.VALUEの変化ではなく、最初のレベルの変化を監視します。
エッセンス:ref(10)-> react({value:10})。これは、最下層が本質的に最初の層であるためです。

<script>
import {shallowReactive} from 'vue'
import {shallowRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowRef({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.value.a='1';
      state.value.gf.b='2';
      state.value.gf.f.c='3';
      state.value.gf.f.s.d='4'
      console.log(state)
      console.log(state.value)
      console.log(state.value.gf)
      console.log(state.value.gf.f.s)
    }
    return {state,myFn}
  }
}

ここに画像の説明を挿入
したがって、上記の文字は数字にはなりませんでした。数値に変換したい場合は、直接状態を変更する必要があります

<script>
import {shallowReactive} from 'vue'
import {shallowRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowRef({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.value={
          a:'4',
          gf:{
            b:'5',
            f:{
              c:'6',
              s:{
                d:'7'
              }
            }
          }
      }
      state.value.a='1';
      state.value.gf.b='2';
      state.value.gf.f.c='3';
      state.value.gf.f.s.d='4'
      console.log(state)
      console.log(state.value)
      console.log(state.value.gf)
      console.log(state.value.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

ここに画像の説明を挿入

③shallowRefは第4層のデータのみを変更したい。第4層が変更されると、UIインターフェースが自動的に変更される。triggerRefとともに使用します。
[注] Vue3はtriggerRefメソッドのみを提供し、TriggerReactiveメソッドは提供しません。したがって、リアクティブタイプのデータの場合、インターフェイスの更新をアクティブにトリガーすることはできません。

<script>
import {shallowReactive} from 'vue'
import {shallowRef,triggerRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let state=shallowRef({
      a:'a',
      gf:{
        b:'b',
        f:{
          c:'c',
          s:{
            d:'d'
          }
        }
      }
    })
    function myFn(){
      state.value.gf.f.s.d='8';
      triggerRef(state)
      console.log(state)
      console.log(state.value)
      console.log(state.value.gf)
      console.log(state.value.gf.f.s)
    }
    return {state,myFn}
  }
}


</script>

ここに画像の説明を挿入

6.toRaw()元のデータは変更されますが、UIは更新されません

ref / reactiveデータ型の特性:
すべての変更が追跡され、UIインターフェイスが更新されます。しかし、これは実際には非常にパフォーマンスを消費します。uiインターフェースを更新する必要がない場合は、toRawメソッドを使用して元のデータを取得できます。このとき、元のデータが変更された場合、そのデータは追跡されず、UIインターフェースは更新されません。

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,toRaw} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let state=reactive(obj)//注意:如果这里是ref的话,下面toRaw(state.value)
    let obj2=toRaw(state)
    function myFn(){
      // state.name="Angle";//会更新ui界面
      obj2.name="Angle";//数据虽然被改变了,不会更新ui界面。这样会减少性能的消耗
      console.log(obj2)
    }
    return {state,myFn}
  }
}


</script>

ここに画像の説明を挿入

7.markRaw()は元のデータを確認し、追跡されることはありません

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,markRaw} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    obj=markRaw(obj)//永远不会被追踪
    let state=reactive(obj)
    function myFn(){
      state.name="Angle";
      console.log(obj)
    }
    return {state,myFn}
  }
}


</script>

ここに画像の説明を挿入

8. toRef()、toRefおよびref、toRefおよびtoRefs

toRefのアプリケーションシナリオ:
応答データを前のデータに関連付けたいが、応答データの更新後にUIを更新したくない場合。

refとtoRefの違い:
ref:コピーと同等、応答データの変更は前のデータに影響しません; toRef:引用と同等、応答データの変更は前のデータに影響します;
ref:データが変更されるとインターフェースが更新されます; toRef:データが変更され、インターフェースは更新されません。

ref->元のデータを変更せずに、かなり新しいコピー。ただし、refパッケージのデータは変更されており、その変更によりページが更新されます。

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,ref} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let state=ref(obj.name)
    function myFn(){
      state.value="Angle";
      console.log(obj)//没有改变obj
      console.log(state)//state是新的复制出来的一份
    }
    return {state,myFn}
  }
}


</script>

ここに画像の説明を挿入
-> toRef参照、元のデータは変更されますが、インターフェースは更新されません:

<template>
  <div>
    {
   
   {state}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {reactive,toRef} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let state=toRef(obj,'name')
    function myFn(){
      state.value="Angle";
      console.log(obj)//因为引用,所以改变了
      console.log(state)//改变了,但界面没更新
    }
    return {state,myFn}
  }
}


</script>

ここに画像の説明を挿入
toRefsは、toRefを複数回使用するための省略形です。

<script>
import {reactive,toRef,toRefs} from 'vue'
export default {
  name: 'App',
  setup(){
    let obj={name:'小李',age:16}
    let name=toRef(obj,'name');
    let age=toRef(obj,'age');
    // let state=toRef(obj);//简写
    function myFn(){
      name.value="Angle";
      age.value=18;
      // state.name.value='Angle';
      // state.age.value=18;
      console.log(obj)//因为引用,所以改变了
      console.log(state)//改变了,但界面没更新
    }
    return {state,myFn}
  }
}


</script>

9.customRef()カスタム参照

refオブジェクトを返します。これは、それに応じて追跡およびトリガーできます。
Track()は、get時に
トリガーされ、このデータが変更を追跡する必要があることをvueに通知します。設定されると、trigger()がトリガーされます。インターフェイスの更新をトリガーするようにvueに指示します。

<template>
  <div>
    {
   
   {age}}
    <button @click='myFn'>按钮</button>
  </div>
</template>

<script>
import {ref,customRef} from 'vue'
function myRef(value){
  return customRef((track,trigger)=>{
    return{
      get(){
        track();//告诉vue这个数据是需要追踪变化的
        console.log('get',value)
        return value;
      },
      set(newValue){
        console.log('set',newValue)
        value=newValue;
        trigger();//告诉vue触发界面更新
      }
    }
  })
}
export default {
  name: 'App',
  setup(){
   let age=myRef(18);
   function myFn(){
     age.value+=1;
   }
    return {age,myFn}
  }
}


</script>

使用シナリオ:非同期リクエストは、非同期のようには見えないカスタマイズに便利です。

<template>
  <div>
    <ul>
      <li v-for="item in state" :key="item.id">{
   
   {item.name}}</li>
    </ul>
  </div>
</template>

<script>
import {ref,customRef} from 'vue'
function myRef(value){
  return customRef((track,trigger)=>{
      //异步
      fetch(value)
      .then((res)=>{
        return res.json()
      })
      .then((data)=>{
        console.log(data);
        value=data;
        trigger();
      })
      .then((err)=>{
        console.log(err)
      })
    return{
      get(){//不能在get中发送异步请求,否则会死循环
        track();//告诉vue这个数据是需要追踪变化的
        console.log('get',value)
        return value;
      },
      set(newValue){
        console.log('set',newValue)
        value=newValue;
        trigger();//告诉vue触发界面更新
      }
    }
  })
}
export default {
  name: 'App',
  setup(){
   let state=myRef('./assets/data.json')
    return {state}
  }
}


</script>

おすすめ

転載: blog.csdn.net/weixin_44727080/article/details/112977564