[vue]組件的創建(componet)和銷毀(keep-alive緩存)和父子dom同步nextTick


思路:
1. 組件的好處,重用性
2. 組件對的slot用法
3. 子如何調用父的數據
4. 子如何觸發父的方法執行
5. 父如何觸發子的方法執行

6. 如何創建組件和銷毀自建--如何緩存避免每次切換創建

研究一下組件的銷毀

- componet是vue內置命令,用於調用顯示子組件
is="home": 根據組件名html通過is=""獲取.

如下我定義了兩個組件,home,list,然后我在html里將2個組件顯示出來
componet事實上是創建了組件.

<div id="app">
    <h1>顯示組件</h1>
    <componet is="home"></componet>
    <componet is="list"></componet>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: "#app",
        components: {
            home: {
                template: "<div>home</div>",
            },
            list: {
                template: "<div>list</div>",
            }
        },
    })
</script>
- 想要實現兩個radio動態切換,類似頁卡效果

- componet事實上是創建了組件.那么如何銷毀組件呢

1.數據綁定到2個radio(注2個radio用value標識為一組)
2.componet獲取radio的值作為自己獲取的組件名
    1.動態獲取:is="radio"

<div id="app">
    <h1>組件動態切換</h1>
    home: <input type="radio" value="home" v-model="radio">
    list: <input type="radio" value="list" v-model="radio"> <br>
    <componet :is="radio"></componet>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            radio: 'home'
        },
        components: {
            home: {
                template: "<div>home</div>",
            },
            list: {
                template: "<div>list</div>",
            }
        },
    })
</script>

- 用vue生命周期函數,研究下切換componet時候,每次都存在創建,銷毀, 浪費資源了.
    1.使用created/mounted 標識創建前動作
    2.使用beforeDestory   標識銷毀前動作
- keep-alive命令緩存componet,不至於每次都銷毀創建, 節約資源.

<div id="app">
    <h1>組件動態切換</h1>
    home: <input type="radio" value="home" v-model="radio">
    list: <input type="radio" value="list" v-model="radio"> <br>
    <keep-alive>
        <componet :is="radio"></componet>
    </keep-alive>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            radio: 'home'
        },
        components: {
            home: {
                template: "<div>home</div>",
                mounted(){alert("創建前")},
                beforeDestroy(){alert("銷毀前")}
            },
            list: {
                template: "<div>list</div>",
                mounted(){alert("創建前")},
                beforeDestroy(){alert("銷毀前")}
            }
        },
    })
</script>

1.先子組件的mounted
    1,異步的,不會等dom渲染
    
2.在父組件的mounted

3.如果父操作子類的dom,要加上nextTick才能保證同步.(即子選mounted,后渲染,然后父mounted獲取到子渲染后的數據)
mounted(){
    console.log(this.$refs.child.$el.innerHTML); //<li>1</li><li>2</li><li>3</li>
},
mounted(){
    this.$nextTick(()=>{ // 想操作dom 就加一個nextTick
        console.log(this.$refs.child.$el.innerHTML); //<li>4</li><li>5</li><li>6</li>
    })
},
<div id="app">
    <child ref="child"></child>
</div>
<!--子組件和父組件同時擁有mounted方法 會先走誰?-->
<!--需要等待子組件掛載完成后在觸發父組件的掛載-->
<template id="child">
    <div>
        <li v-for="a in arr">{{a}}</li>
    </div>
</template>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el:'#app',
        mounted(){
            this.$nextTick(()=>{ // 想操作dom 就加一個nextTick
                console.log(this.$refs.child.$el.innerHTML);
            })
        },
        components:{
            child:{
                template:'#child',
                data(){
                  return {arr:[1,2,3]}
                },
                mounted(){
                   this.arr = [4,5,6] // 此處是異步渲染dom
                }
            }
        }
    })
</script>

pannel栗子

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>maotai http://www.zhufengpeixun.cn</title>
  <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css">
</head>
<body>
<div id="app">
  <panel type="warning" @say-title="parent">
    <div slot="title">這是一篇vue的使用</div>
    <div slot="content">內容區
      <p>組件的屬性傳遞</p>
      <p>slot的用法</p>
      <p>ref的使用</p>
      <p>nextTick的用法</p>
    </div>
    <div>作者:zfpx</div>
  </panel>
</div>
<template id="panel">
  <div class="panel" :class="[color]">
    <div class="panel-heading" ref="head">
      <slot name="title"></slot>
    </div>
    <div class="panel-body">
      <slot name="content"></slot>
    </div>
    <div class="panel-footer">
      <slot>匿名</slot>
      <button @click="say">點我說標題</button>
    </div>
  </div>
</template>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
  let panel = {
      template:'#panel',
      computed:{
          color(){return 'panel-'+this.type}
      },
      methods:{
          say(){this.$emit('say-title',this.$refs.head.innerText)}
      },
      props:{
          type:{ // this.type = 'primary'子不能更改父組件傳遞的屬性
              type:[String],
              default:'default'
          }
      }
  };
  let vm = new Vue({
      el:'#app',
      methods:{
        parent(tit){
          alert(tit);
        }
      },
      components:{
          panel
      }
  });
</script>
</body>
</html>

pannel-for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>maotai http://www.zhufengpeixun.cn</title>
    <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css">
</head>
<body>
<div id="app">
    <panel :type="article.type" @say-title="parent" v-for="(article,index) in articles" :key="index">
        <div slot="title"><span v-html="article.title"></span></div>
        <div slot="content">{{article.content}}</div>
        <div v-if="article.auth">{{article.auth}}</div>
    </panel>
</div>
<template id="panel">
    <div class="panel" :class="[color]">
        <div class="panel-heading" ref="head">
            <slot name="title"></slot>
        </div>
        <div class="panel-body">
            <slot name="content"></slot>
        </div>
        <div class="panel-footer">
            <slot>匿名</slot>
            <button @click="say">點我說標題</button>
        </div>
    </div>
</template>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    let panel = {
        template: '#panel',
        computed: {
            color() {
                return 'panel-' + this.type
            }
        },
        methods: {
            say() {
                this.$emit('say-title', this.$refs.head.innerText)
            }
        },
        props: {
            type: { // this.type = 'primary'子不能更改父組件傳遞的屬性
                type: [String],
                default: 'default'
            }
        }
    };
    let vm = new Vue({
        el: '#app',
        data: {
            articles: [
                {type: 'warning', title: '<h2>vue</h2>', content: '這是vue的文章', auth: '作者:zfpx'},
                {type: 'primary', title: '<h2>react</h2>', content: '這是react的文章'},
                {type: 'danger', title: '<h2>angular</h2>', content: '這是react的文章'},
            ]
        },
        methods: {
            parent(tit) {
                alert(tit);
            }
        },
        components: {
            panel
        }
    });
</script>
</body>
</html>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM