zoukankan      html  css  js  c++  java
  • [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>
    
  • 相关阅读:
    正则表达式口诀
    Ajax请求的四种方式
    jQuery插件 -- jQuery UI插件
    电脑操作技巧
    递归
    声纹识别环境初次搭建
    视频编码book_实战_全角度——1
    SDK等阅读笔记
    音视频bug调试
    音视频开发进阶指南(二)
  • 原文地址:https://www.cnblogs.com/iiiiiher/p/9033391.html
Copyright © 2011-2022 走看看