Vue2 (ライフサイクル、リストの並べ替え、計算されたプロパティとリスナー)

序文

ブログの最後の章では Vue の基本について説明しましたが、
この章では、Vue のライフ サイクル、リスト フィルタリング、計算プロパティ、リスナーについて説明します。

1. ライフサイクル

  • 通常、ライフ サイクル コールバック関数、ライフ サイクル関数、ライフ サイクル フックとも呼ばれます。
  • vue の初期化中にさまざまな段階で呼び出されるさまざまな関数
  • ライフサイクル関数はthisvue インスタンスを指しており、名前は変更できません

1.1、ライフサイクル関数の概要

「ライフサイクル」とは、コンストラクターの開始(作成)から GC(ガベージ コレクション)のリサイクルと破棄までのインスタンス オブジェクトが存在する全期間を指します。

実際の開発プロセスでは、ライフサイクル機能の使用頻度が比較的高く、使いこなすことに注力する必要があります。

1.2、Vueの初期化プロセス

ここに画像の説明を挿入

  • beforeステージの作成
    • vue のデータとデータのメソッドはまだ使用できません
  • 作成されたステージ
    • vue のデータとデータのメソッドを使用する準備ができました。
  • マウントステージ前
    • ページはコンテンツを表示できますが、コンパイルされていないため、最終的には操作不能な DOM 構造となり、表示時間が短いです
  • 取り付けられた
    • このページにはコンパイルされた DOM が表示されます
    • vueの初期化処理が終了する
    • このステージは、タイマー、ネットワーク要求、サブスクリプション メッセージ、バインディング イベントなどで実行できます。

1.3、Vueの更新プロセス

ここに画像の説明を挿入

  • 更新前
    • データは新しく、ページは更新されていません
  • 更新しました
    • データは新しく、ページは同期して更新されます

1.4、Vueの破棄プロセス

ここに画像の説明を挿入

  • 前に破壊する
    • この段階でタイマーをオフにしたり登録を解除したりできます
    • データとメソッドにはアクセスできますが、更新はトリガーされません
  • 破壊する
    • すべて終わった

1.5、ライフサイクルを見直す

  • ライフサイクル機能
    • 作成前、作成後(beforeCreate、created)
    • 実装前、実装後(beforeMount、実装済み)
    • アップデート前、アップデート後(beforeUpdate、updated)
    • 破壊前、破壊後(beforeDestroy、破壊されました)
  • よく使用されるライフサイクル関数
    • 取り付けられた
      • タイマーを開始します
      • Ajaxリクエストを送信する
      • ニュースを購読する
      • カスタムイベントをバインドする
    • 前に破壊する
      • タイマーをクリアする
      • 購読解除、イベントリスナー
      • カスタムイベントのバインドを解除する
  • vue インスタンスが破壊されました
    • vue開発者ツールのデータが空です
    • カスタム イベントは破棄後に失敗します
    • beforeDestroy ではデータ操作を実行せず、更新プロセスも実行しません。

1.,6, コードデモ

1.6-1,作成前
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {
   
   {myName}}
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                myName:"abc"
            }
        },
        beforeCreate(){
      
      
            var bobyDom = document.getElementsByTagName("body")[0].innerHTML
            // beforeCreate中,data的数据是没有被定义的
            console.log("beforeCreate",this.myName,bobyDom);
        },
    })
</script>
</html>

ここに画像の説明を挿入

1.6-2、作成
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {
   
   {myName}}
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                myName:"abc"
            }
        },
        created(){
      
      
            var bobyDom = document.getElementsByTagName("body")[0].innerHTML
            // 做一下页面的数据初始化工作。比如说发起ajax请求
            console.log("created",this.myName,bobyDom);
        },
    })
</script>
</html>

ここに画像の説明を挿入

1.6-3、マウント前
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {
   
   {myName}}
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                myName:"abc"
            }
        },
        beforeMount(){
      
      
            var bobyDom = document.getElementsByTagName("body")[0].innerHTML
            
            console.log("beforeMount",this.myName,bobyDom);
        },
    })
</script>
</html>

ここに画像の説明を挿入

1.6-4、取り付け済み
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {
   
   {myName}}
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                myName:"abc"
            }
        },
        mounted(){
      
      
            var bobyDom = document.getElementsByTagName("body")[0].innerHTML
            // 数据已经渲染到View中
            console.log("mounted",this.myName,bobyDom);
        },
    })
</script>
</html>

ここに画像の説明を挿入

1.6-5、アップデート前
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {
   
   {myName}}
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                myName:"abc"
            }
        },
        beforeUpdate(){
      
      
            var bobyDom = document.getElementsByTagName("body")[0].innerHTML
            // 数据更新前,数据未改变
            console.log("beforeUpdate",this.myName,bobyDom);
        },
    })
</script>
</html>

ここに画像の説明を挿入

1.6-6、更新
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        {
   
   {myName}}
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                myName:"abc"
            }
        },
        updated(){
      
      
            var bobyDom = document.getElementsByTagName("body")[0].innerHTML
            // 数据更新后,数据已改变
            console.log("updated",this.myName,bobyDom);
        }
    })
</script>
</html>

ここに画像の説明を挿入

1.7、ライフサイクル機能の使用シナリオ

  • beforeCreate ライフサイクル関数の実行中に、読み込みアニメーションを追加できます
  • 作成したライフサイクル関数の実行中に、読み込みアニメーションを終了し、関数の自己実行やその他の操作を実現するために初期化を行うことができます。
  • 最も一般的に使用されるのは、マウントされたライフサイクル関数です
    • バックエンドデータリクエストを開始してデータを取得できます
    • ページ間で渡されるパラメータを受け取ることができます
    • 子コンポーネントから親コンポーネントなどにパラメータを渡すことができます。

次に、vue でのリストの並べ替え

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <div>
            <input type="text" v-model="searchInput" name="" id="">
            <button @click="paixu(1)">升序</button>
            <button @click="paixu(2)">降序</button>
            <button @click="paixu(3)">原序列</button>
            <div v-for="(item,index) in searchList">
                {
   
   {item.name}}--{
   
   {item.price}}
            </div>
        </div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:'#app',
        data(){
      
      
            return{
      
      
                keyword:0, // 用来排序
                searchInput:"",
                goodList:[
                    {
      
      name:'牛仔裤',price:200},
                    {
      
      name:'运动鞋',price:100},
                    {
      
      name:'跑步鞋',price:300},
                    {
      
      name:'篮球鞋',price:400},
                ],
            }
        },
        methods:{
      
      
            paixu(val){
      
      
                this.keyword=val
            }
        },
        computed:{
      
      
            searchList(){
      
      
                // 把goodList的内容过滤,把符合条件的形成一个新的数组
                // filter是数字的过滤方法,这个方法的参数是一个函数,此函数返回true,则把此项返回新的数组中
                let list = this.goodList.filter((item)=>{
      
      
                    return item.name.indexOf(this.searchInput)!==-1
                })

                if(this.keyword){
      
      
                    list.sort((a1,a2)=>{
      
      
                        return this.keyword === 1
                        ? a1.price - a2.price
                        : a2.price - a1.price
                    })
                }

                return list
            }
        }
    })
</script>
</html>

ここに画像の説明を挿入

2.1、vueのデータ更新の問題

2.1-1、オブジェクト新規データ更新問題
  • 説明する
    • 通常のオブジェクトを介して属性メソッドを追加すると、Vue は検出できず、応答しません
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <div v-for="(attr,key) in person">
            {
   
   {key}} -- {
   
   {attr}}
        </div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:'#app',
        data(){
      
      
            return{
      
      
                person:{
      
      
                    name:'张三',
                    sex:'男',
                }
            }
        },
    
    })
</script>
</html>

ここに画像の説明を挿入
この方法で追加しても、オブジェクトのようにデータ変更を監視するゲッターとセッターはカプセル化されません。

  • 解決する
    • Vue.set() / this.$set
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <div v-for="(attr,key) in person">
            {
   
   {key}} -- {
   
   {attr}}
        </div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:'#app',
        data(){
      
      
            return{
      
      
                person:{
      
      
                    name:'张三',
                    sex:'男',
                }
            }
        },
    
    })
</script>
</html>

ここに画像の説明を挿入

  • 知らせ
    • this.$set は、vue インスタンスのルート データ オブジェクトにプロパティを追加できません
2.1-1、配列データ更新の問題
  • 説明する
    • 配列のインデックス値を介して配列のデータを直接変更すると、Vue は変更を検出できません
    • js実際には、データの最初の項目がメモリ内で変更されています
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <div v-for="(attr,key) in person">
            {
   
   {key}} -- {
   
   {attr}}
        </div>
        <div>
            <input type="text" v-model="searchInput" name="" id="">
            <button @click="paixu(1)">升序</button>
            <button @click="paixu(2)">降序</button>
            <button @click="paixu(3)">原序列</button>
            <div v-for="(item,index) in searchList">
                {
   
   {item.name}}--{
   
   {item.price}}
            </div>
        </div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:'#app',
        data(){
      
      
            return{
      
      
                keyword:0, // 用来排序
                searchInput:"",
                goodList:[
                    {
      
      name:'牛仔裤',price:200},
                    {
      
      name:'运动鞋',price:100},
                    {
      
      name:'跑步鞋',price:300},
                    {
      
      name:'篮球鞋',price:400},
                ],
                person:{
      
      
                    name:'张三',
                    sex:'男',
                }
            }
        },
        methods:{
      
      
            paixu(val){
      
      
                this.keyword=val
            }
        },
        computed:{
      
      
            searchList(){
      
      
                // 把goodList的内容过滤,把符合条件的形成一个新的数组
                // filter是数字的过滤方法,这个方法的参数是一个函数,此函数返回true,则把此项返回新的数组中
                let list = this.goodList.filter((item)=>{
      
      
                    return item.name.indexOf(this.searchInput)!==-1
                })

                if(this.keyword){
      
      
                    list.sort((a1,a2)=>{
      
      
                        return this.keyword === 1
                        ? a1.price - a2.price
                        : a2.price - a1.price
                    })
                }

                return list
            }
        }
    })
</script>
</html>

ここに画像の説明を挿入

  • 理由
    • Vue の配列は、オブジェクトのようにデータの変更を監視するゲッターとセッターをカプセル化していないためです。
  • 解決する
    • Vue は、配列の元の操作メソッドでテンプレートを再解析するメソッドをラップします。つまり、データ内の配列操作メソッドはネイティブではなく、Vue によってカプセル化されます。
    • どの配列操作メソッドがカプセル化されていますか?
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
pop() 删除数组的最后一个元素并返回删除的元素
shift()  删除并返回数组的第一个元素
unshift()  向数组的开头添加一个或更多元素,并返回新的长度。
splice()  从数组中添加或删除元素。
sort()   对数组的元素进行排序
reverse() 反转数组的元素顺序。

3、計算された属性

計算されたプロパティ。メソッド名はオブジェクト内で直接使用できます。このプロパティは計算されます。
このメソッドのプロパティを変更すると、このメソッドがトリガーされます
。 使用シナリオ: メソッドに計算ビジネス ロジックを組み込みたいと考えています。たとえば、氏名の計算、住所の計算、ショッピング カートの合計などです。

以下の例では、3 つのメソッドを使用します。

  • 達成するためのメソッドを使用する
  • vue の計算された読み取りおよび書き込みメソッドを使用して、次のことを実現します。
  • vue の計算読み取り専用メソッドを使用して実装

注: 計算メソッドを使用することをお勧めします。キャッシュメカニズムがあります。ページが複数回繰り返し呼び出された場合、実行されるのは 1 回だけです

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <div>
            <input type="text" v-model="firstName" ><br>
            <input type="text" v-model="lastName" ><br>
            <input type="text" v-model="getFullName()" ><br>
            <input type="text" v-model="fullNameReadOnly" ><br>
            <input type="text" v-model="funName" ><br>
        </div>
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                firstName:'科比',
                lastName:'布莱恩特',
            }
        },
        methods:{
      
      
            getFullName(){
      
      
                return this.firstName + "-" + this.lastName
            }
        },
        computed:{
      
      
            // 只读方式的简写
            fullNameReadOnly(){
      
      
                return this.firstName + "-" + this.lastName
            },
            funName:{
      
      
                get(){
      
      
                    return this.firstName + "-" + this.lastName
                },
                set(value){
      
      
                    this.firstName = value.split("-")[0]
                    this.lastName = value.split("-")[1]
                }
            }
        },
    })
</script>
</html>

ここに画像の説明を挿入

4 番目に、監視属性監視

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        
    </div>
</body>
<script src="../js/vue2.7.js"></script>
<script>
    var app = new Vue({
      
      
        el:"#app",
        data(){
      
      
            return{
      
      
                isSunny:true,
                person:{
      
      
                    age:18,
                    name:'王导',
                }
            }
        },
        watch:{
      
      
            // 表示要对isSunny这个属性进行监听
            isSunny(newVal,oldVal){
      
      
                console.log("改变了",oldVal,newVal);
            },

            // 深度监听可以用来监听整个对象的改变,但要慎重使用,因为消耗性能 
            person:{
      
      
                deep:true,
                handler(oldVal,newVal){
      
      
                    console.log("改变了",oldVal,newVal);
                }
            },
            "person.name"(oldVal,newVal){
      
      
                    console.log("我也监听了");
            }
        }
    })
</script>
</html>

ここに画像の説明を挿入

やっと

送大家一句话: 世界上的好东西都是抢来的,只有弱者才会坐等分配

おすすめ

転載: blog.csdn.net/H20031011/article/details/132166095