vue組件的詳細介紹

核心目標

為了可重用性高,減少重復性開發(fā),我們可以按照template、style、script的拆分方式,放置到對應的.vue文件中。

組件概括

vue組件可以理解為預先定義好的ViewModel類。一個組件可以預定義很多選項,最核心的有:
  1. 模板template:模板反映了數(shù)據(jù)和最終展現(xiàn)給用戶的DOM之間的映射關系,
  2. 初始數(shù)據(jù)data:一個組件的初始數(shù)據(jù)狀態(tài),對于可重復的組件來說,通常是私有的狀態(tài)。
  3. 接收的外部的參數(shù)(props):組件之間通過參數(shù)來進行數(shù)據(jù)的傳遞和共享,參數(shù)默認是單項綁定,但也可以顯示聲明為雙向綁定。
  4. 方法(methods):對數(shù)據(jù)的改動操作一般都在組件內進行??梢酝ㄟ^v-on指令將用戶輸入事件和組件方法進行綁定。
  5. 生命周期函數(shù)(鉤子函數(shù)):一個組件會觸發(fā)多個生命周期函數(shù),在這些鉤子函數(shù)中可以封裝一些自定義邏輯??梢岳斫鉃閏ontroller的邏輯被分散到了這些鉤子函數(shù)中。

注冊組件

注冊組件就是利用Vue.component()方法,先傳入一個自定義組件的名字,然后傳入這個組件的配置。

(組件名不要帶有大寫字母,多個單詞使用中劃線my-dom)

  • 全局組件
    (直接使用Vue.component()創(chuàng)建的組件,所有的Vue實例都可以使用。)
    (一般寫插件的時候全局組件使用多一些)
 Vue.component('mycomponent',{      //自定義組件名mycomponent
    template: `<div>這是一個自定義組件</div>`,
    data () {
      return {
        message: 'hello world'
      }
    }
  })
  • 局部注冊組件
    使用三部曲1.創(chuàng)建這個組件;2.注冊這個組件;3.使用這個組件;
<div id="app">
    <mycomponent></mycomponent>   //3.組件的使用
    <my-component></my-component>    //3.組件的使用
</div>
<script>
  //1.創(chuàng)建這個組件
  let  mycomponent={
      template: `<div>這是一個局部的自定義組件,只能在當前Vue實例中使用{{aa}}</div>`,
      data(){
        return {'aa':'hello'}
      }
   };

  let  app = new Vue({
    el: '#app',
    data: {
    },
    components: {
      mycomponent,//2.注冊這個組件
      }
    }
  })
</script>
  • 模板的要求:組件的模板只能有一個根元素。
template: `<div>
                元素1.....
                元素2.....
                元素3.....
           </div>`,
  • 組件中的data必須是函數(shù)。
data:function(){
            return {'aaa':'bbb'}//template中可以使用aaa
        },
  • 組件的屬性props。
    Vue組件通過props屬性來聲明一個自己的屬性,然后父組件就可以往里面?zhèn)鬟f數(shù)據(jù)。
<div id="app1">
    動態(tài)操作屬性:name是變量(讀取實例中data的值)
    <hello :n="name"></hello>
</div>
<div id="app2">
    靜態(tài)的屬性:name是常量(就是name)
    <hello n="name"></hello>
</div>
<script>
    Vue.component('hello',{
        props:['n'],//通過父組件傳過來的數(shù)據(jù) name變量
        data:function(){
            return {'aaa':'bbb'}
        },
        template:'<p>{{aaa}} {{n}}</p>'
    })
    var app1=new Vue({
        el:'#app1',
        data:{
            name:'haha'
        }
    })
    var app2=new Vue({
        el:'#app2',
        data:{
            name:'haha'
        }
    })
</script>

渲染結果


props.png
  • props的驗證。

組件之間的通信

子組件給父組件傳遞數(shù)據(jù),利用事件的訂閱發(fā)布模式
  • 1.給子組件的template上的元素綁定事件(如click),執(zhí)行子組件的方法(如changeData),子組件的方法中發(fā)射一個事件(如s),傳一個數(shù)據(jù)(如lalala);
  • 2.父組件中,定義一個方法(如getData)用來拿到子組件的數(shù)據(jù)。
  • 3.在自定義的組件上綁定子組件傳過去的事件(s),執(zhí)行事件(s)執(zhí)行的是getData函數(shù),getData函數(shù)中拿到數(shù)據(jù)(data,就是子組件傳過去的lalala)。
<div id="app">
    <parent></parent>
</div>
<template id="parent">
    <div>
        <p>父組件{{msg}}</p>//點擊子組件觸發(fā)getData獲取到子組件轉來的msg數(shù)據(jù),綁定到父組件上
        <children @s="getData"></children>
    </div>
</template>
<script>
    var app=new Vue({
        el:'#app',
        components:{
            parent:{
                template:'#parent',
                data(){
                    return {msg:'aaa'};
                },
                methods:{
                    getData(data){
                        alert(data);//子組件傳過來的數(shù)據(jù)
                        this.msg=data;
                    }
                },
                components:{
                    children:{
                        template:'<p @click="changeData">子組件</p>',
                        methods:{
                            changeData(){
                                this.$emit('s','lalala');//傳遞給父組件
                            }
                        }
                    }
                }
            }
        }
    })
</script>
父組件給子組件傳遞數(shù)據(jù)(利用props屬性)
<div id="app">
    <parent></parent>
</div>

<script>
    var app=new Vue({
        el:'#app',
        components:{//一個父組件里邊可以包含多個子組件
            parent:{
                template:'<h1 >{{msg}},父組件<children :n="msg"></children></h1>',
                data:function(){//父組件的數(shù)據(jù) 傳給子組件
                    return {msg:'hello'}
                },
                components:{
                  children:{
                      props:['n'],//根據(jù)props拿到父組件中寫的動態(tài)屬性拿到數(shù)據(jù)
                      template:'<h2>{{n}},子組件</h2>',
                  }
                }
            }
        }
    })
兄弟組件之間傳遞數(shù)據(jù) (事件車---原理也是事件的訂閱發(fā)布模式)
注意:
  • 每一個vue的實例都是獨立的;相互之間不能直接進行改變數(shù)據(jù);
  • 給兩個不同的組件找一個載體;把共同的方法放在這個載體上;
  • 這個載體就是 let eventBus = new Vue; // 創(chuàng)建一個新的vue實例;
  • 在這個新的實例上,有 $on: 訂閱 $emit: 發(fā)布;
  • $on的綁定要基于鉤子函數(shù),一般放在created或者mounted上
<div id="app">
    <tmp1></tmp1>
    <tmp2></tmp2>
</div>

<script>
    var eventBus=new Vue();
    var app = new Vue({
        el: '#app',
        data: {},
        components: {
            tmp1: {
                template: "<h1>組件1{{msg}}</h1>",
                data(){
                    return {msg:""}
                },
                mounted(){//鉤子函數(shù),頁面一加載進來的時候就已經綁定好了
                   eventBus.$on('aaa',(data)=>{
                        this.msg=data;
                    })
                }
            },
            tmp2: {
                template: "<h1 @click='sendData'>組件2{{msg}}</h1>",
                data(){
                    return {msg: 'hello'}
                },
                methods:{
                    sendData(){
                        //發(fā)布數(shù)據(jù)
                        eventBus.$emit('aaa',this.msg)
                    }
                }
            }
        }
    })
</script>

數(shù)據(jù)同步(子組件的數(shù)據(jù)和父組件保持一致)

數(shù)據(jù)同步的核心:父組件給子組件傳遞“引用數(shù)據(jù)類型的數(shù)據(jù)”;
<div id="app">
<parent></parent>
</div>
<template id="parent">
<div>
    <h1>父組件 <mark>{{msg.name}}</mark></h1>
    <children :n="msg"></children>
</div>
</template>
<template id="children">
    <h2 @click="changeData">子組件 {{n.name}}</h2>
</template>
<script>
    //數(shù)據(jù)同步的核心:父組件給子組件傳遞“引用數(shù)據(jù)類型的數(shù)據(jù)”;
    var app=new Vue({
        el:'#app',
        components:{
            parent:{
                template:'#parent',
                data(){
                    return {msg:{name:'hahha'}}
                },
                components:{
                    children:{
                        props:['n'],
                        template:'#children',
                        methods:{
                            changeData(){
                                this.n.name='lallala'
                            },
                        }
                    }

                }
            }
        }
    })
</script>
數(shù)據(jù)不同步(不直接使用父組件傳的值,用data屬性再自己的組件內做一個中間變量,防止報錯)
<parent></parent>
</div>
<template id="parent">
<div>
    <h1>父組件 <mark>{{msg}}</mark></h1>
    <children :n="msg"></children>
</div>
</template>
<script>
    //數(shù)據(jù)不同步的核心:中間變量接收避免報錯;
    var app=new Vue({
        el:'#app',
        components:{
            parent:{
                template:'#parent',
                data(){
                    return {msg:'hahha'}
                },
                components:{
                    children:{
                        props:['n'],
                        template:'<h2 @click="changeData">子組件 {}</h2>',
                        data(){
                            return {b:this.n}
                        },
                        methods:{
                            changeData(){
                                this.b='lallala'
                            },
                        }
                    }
                }
            }
        }
    })
</script>

組件切換

js動態(tài)控制template(也可以用is屬性控制)
<div id="app">
    <div class="container">
        <div @click="comp='zujian1'">顯示組件1</div>
        <div @click="comp='zujian2'">顯示組件2</div>
    </div>
    <!--aaa標簽是核心,必須得寫,通過is決定顯示那個組件-->
    <aaa :is="comp"></aaa>
</div>

<script>
    var app=new Vue({
        el:'#app',
        data:{
            comp:'zujian2',
        },
        components:{
            zujian1:{
                template:'<h1>組件1</h1>'
            },
            zujian2:{
                template:'<h1>組件2</h1>'
            }
        }
    })
</script>

插槽(slot官網(wǎng)有詳細介紹)

slot相當于子組件設置了一個地方,如果在調用它的時候,往它的開閉標簽之間放了東西,那么它就把這些東西放到slot中。
  1. 當子組件中沒有slot時,父組件放在子組件標簽內的東西將被丟棄;
  2. 子組件的slot標簽內可以放置內容,當父組件沒有放置內容在子組件標簽內時,slot中的內容會渲染出來;
  3. 當父組件在子組件標簽內放置了內容時,slot中的內容被丟棄
    實例:
<div id="app">
    <hello>//使用組件
        lalalala
        <!--給插槽起好名字-->
        <div slot="div1">1111111111111</div>
        <div slot="div2">2222222222222</div>
    </hello>
</div>
<template id="temp1">//模板
    <h1>
        hello
        <!--無名插槽-->
        <slot></slot>
        <!--有名插槽 可以根據(jù)插槽切換順序-->
        <slot name="div2"></slot>
        <slot name="div1"></slot>
    </h1>
</template>
<script>
    var app=new Vue({
        el:'#app',
        data:{

        },
        components:{
            hello:{
                template:"#temp1"
            }
        }
    })

組件文件示例

父組件.vue

<template>
    <div class="">
        <div class="home-container">
            <Banner></Banner>
            <quick-link :allAmount="allAmount"> </quick-link>
            <Recommended></Recommended>
        </div>
       <m-footer></m-footer>
    </div>
</template>

<script>
    import axios from 'axios'
    import MFooter from '../footer.vue'
    import Banner from './banner.vue'
    import QuickLink from './quickLink.vue'
    import Recommended from './recommended.vue'
    import {setSession} from '../../common/userCenter'
    import {loadAppHomeAct,loadStatisticalData} from '../../api/api'
    export default {
        data(){
            return{
                allAmount:[]
            }
        },
        components:{
            MFooter,
            Banner,
            QuickLink,
            Recommended
        },
        created(){
            this.fetchCookies();
        },
        methods:{
           getQueryString: function (name) {
                var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
                var url=decodeURIComponent(window.location.search);
                var r = url.substr(1).match(reg);
                if (r != null) return (r[2]);
                return "";
            }
        }
    }
</script>

<style>
    @import "home.css";
</style>

鏈接到路由配置

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容