Vue 組件基礎(chǔ)

官方教程: https://cn.vuejs.org/v2/guide

聲明組件

let myComponent = Vue.extend({
    template : '#my',
    // 此時的 #my 是id="my"的template標(biāo)簽
});

// 可以簡化為
let myComponent = {
    template : '#my',
    data(){
        // 此處的data必須是一個函數(shù)
    }
};

注冊組件(全局組件, 局部組件)

// 全局組件: 一次注冊在所有的vue實例中(都能夠使用
Vue.component('my-component',{
    template : '#my-component',
    data () {
        // 此處的data必須是一個函數(shù)    
    },
});

// 局部組件: 只能在某一個vue實例中使用
const vm = new Vue({
    'el' : '#app',
    components : {
        'my-component' : {
            template : '#my',
            data() { 
                // 此處的data必須是一個函數(shù)
            }
        },
    }
});

注: 為了保證各個組件的相互獨立性,所有的組件中的data必須是一個函數(shù)

組件之間的通信

  • 父組件 => 子組件: props
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue study</title>
    <script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
<!-- templates -->
<template id="my">
    <div>
        <p>這是本組件自己的數(shù)據(jù): {{selfData}}</p>
        <p>這是父組件的數(shù)據(jù): {{msg}}</p>
    </div>
</template>
<!-- /templates -->


<!-- 使用組件 -->
<div id="app">
    <my-component :msg="message"></my-component>
</div>


<script>
    // 1.聲明一個組件
    let myComponent = Vue.extend({
        template: '#my',
        props: ["msg"],
        // props 不僅僅可以是一個數(shù)組,也可以是一個對象
        data() {
            return {
                selfData: "hello Vue",
            };
        },
    });
    
    
/** props 支持的類型=========================
 1. 簡單語法
  Vue.component('props-demo-simple', {
    props: ['size', 'myMessage']
  })
  2. 對象語法缩筛,提供校驗
  Vue.component('props-demo-advanced', {
    props: {
      // 檢測類型
      height: Number,
      // 檢測類型 + 其他驗證
      age: {
        type: Number,
        default: 0,
        required: true,
        validator: function (value) {
          return value >= 0
        }
      }
    }
  });
==================================*/

    // 2.在Vue實例中來注冊組件
    const vm = new Vue({
        el: '#app',
        data: {
            message: 'hello world',
        },
        components: {
            // 注冊一個局部組件
            'my-component': myComponent,
            // 注: 此時必須使用 - 分割單詞,或者全部小寫,不能使用駝峰式寫法
        }
    });
</script>
<!--
    父組件 => 子組件: 在子組件中使用父組件的數(shù)據(jù)
    1. 聲明一個組件
    2. 注冊組件(全局或者局部組件都可以通信)
    3. 使用組件(my-component), 并在使用時綁定一個屬性 :msg
    4. 在子組件中用 props 來獲取綁定的屬性   props : ["msg"],
    5. 測試,看是否能夠成功傳遞值
-->
</body>
</html>
  • 子組件 => 父組件: 發(fā)布訂閱
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue study</title>
    <script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <!-- 使用組件 -->
    <my-component :msg="message" @custom_event="changeData"></my-component>
</div>

<!-- templates -->
<template id="my">
    <div>
        <p>{{msg}}</p>
        <p>{{selfData}}</p>
        <!-- <button @click="$emit('custom_enevt','args')">點我改變父組件的數(shù)據(jù)</button> -->
        <!-- 如果覺得這種行內(nèi)的觸發(fā)滿足不了復(fù)雜的邏輯需求,你也可以把這個觸發(fā)寫到這個組件的方法中 -->
         <button @click="triggerParent(10)">點我改變父組件的數(shù)據(jù)</button>
    </div>
</template>

<script>
    // 聲明一個組件
    let myComponent = Vue.extend({
        template: '#my',
        props: ["msg"],
        data() {
            return {
                selfData: 'hello Vue',
            };
        },
        methods : {
            triggerParent(val){
                // 觸發(fā)父組件并傳遞一個參數(shù),此時的val是click調(diào)用時傳遞的參數(shù)
                this.$emit('custom_event', val);
            },
        },
    });

    const vm = new Vue({
        el: '#app',
        data: {
            message: 'hello world',
        },
        methods: {
            changeData (val) {
                // 把message變成一個隨機數(shù)連接上子組件傳遞的參數(shù)
                this.message = val + Math.ceil(Math.random()*100);
            },
        },
        components: {
            // 注冊一個局部組件
            'my-component': myComponent,
        }
    });
</script>
<!--
由于vue為了保證各個組件的獨立性,所以將各個組件的數(shù)據(jù)流向做成那單向數(shù)據(jù)流,
而這樣,就只能父組件改變子組件的內(nèi)容,而不能子組件改變父組件的內(nèi)容
所以為了能夠在子組件中改變父組件的數(shù)據(jù),只有使用自定義事件系統(tǒng)

1. 聲明一個組件  let myComponent = Vue.extend({...});
2. 注冊一個組件(全局,局部都行)
3. 使用組件
    3.1) 綁定一個屬性     :msg="message"  子組件可以用 props 來獲取綁定的屬性
    3.2) 綁定一個自定義事件 @custom_event="changeData" 此時的custom_event是事件名稱,changeData是methods中的方法
    3.3) 子類想改變父類的數(shù)據(jù),可以用$emit('事件名稱')來觸發(fā)父組件的事件,然后由父組件決定改變的規(guī)則,從而達到單向數(shù)據(jù)流的目的
    3.4) 觸發(fā)父類自定義事件
        3.4.1) 行內(nèi)觸發(fā)
            <button @click="$emit('custom_enevt','args')">點我改變父組件的數(shù)據(jù)</button> 此時的args是參數(shù)
        3.4.2) 使用方法觸發(fā)
            <button @click="triggerParent(10)">點我改變父組件的數(shù)據(jù)</button>
            methods : {
                 triggerParent(val){
                     // 觸發(fā)父組件并傳遞一個參數(shù),此時的val是click調(diào)用時傳遞的參數(shù)
                     this.$emit('custom_event', val);
                  },
            }
-->
</body>
</html>
  • 組件嵌套的情況
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue組件嵌套</title>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <style>
        .cmpt1, .cmpt2 {
            color: #ffffff;
            padding: 15px;
        }

        .cmpt1 {
            background: #272822;
        }

        .cmpt2 {
            background: #265a88;
        }
    </style>
</head>
<body>
<div id="app">
    <my-component @custom_event="changeData" :msg="message"></my-component>
</div>

<!-- templates -->
<template id="my">
    <div>
        <one :msg="msg" :name="name"></one>
        <two :msg="msg" @test_event="changeMess"></two>
    </div>
</template>

<!--one-->
<template id="one">
    <div class="cmpt1">
        <p>這是組件1</p>
        <p>這是二級傳遞: hello {{msg}}!!! </p>
        <p>這是三級傳遞: what's your name? my name is {{name}}</p>
    </div>
</template>

<!--two-->
<template id="two">
    <div class="cmpt2">
        <p>這是組件2</p>
        <p> hello {{msg}} </p>
        <p>
            <button @click="changePrentData(10)">點我改變父組件數(shù)據(jù)</button>
        </p>
    </div>
</template>


<script>
    // 聲明一個子組件
    let one = Vue.extend({
        template: '#one',
        props: ["msg", "name"],
    });

    // 聲明一個子組件
    let two = Vue.extend({
        template: '#two',
        props: ["msg"],
        methods: {
            changePrentData(val) {
                let m = Math.ceil(Math.random() * val);
                // this.$emit('custom_event', m);
                this.$emit('test_event', m);
            }
        },
    });

    // 聲明一個父組件
    let myComponent = Vue.extend({
        template: '#my',
        props: ["msg"],
        methods: {
            changeMess(val){
                this.$emit('custom_event',val);
            }
        },
        components: {
            'one': one,
            'two': two
        },
        data() {
            return {
                name: 'Tom',
            };
        }
    });

    const vm = new Vue({
        el: '#app',
        data: {
            message: 'world',
        },
        methods: {
            changeData(val) {
                this.message = "這是改變后的message,喜歡嗎? " + val + " 是點擊是傳遞的參數(shù)";
            }
        },
        components: {
            // 注冊一個局部組件
            'my-component': myComponent,
        }
    });
</script>
<!--
    組件嵌套時,最底層的組件想要與最頂層的組件通信,必須一層一層向上傳遞
-->
</body>
</html>
  • 實例 模態(tài)框
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>蒙版效果</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        html, body {
            width: 100%;
            height: 3000px;
            /* 為了測試滾動 */
        }

        #alert-panel {
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            position: absolute;
            top: 0;
            left: 0;
            /*display: none;*/
        }

        #alert-panel #login {
            width: 500px;
            height: 300px;
            background: #000000;
            position: fixed;
            top: 50%;
            left: 50%;
            margin-left: -250px;
            margin-top: -180px;
        }

        #close-alert-panel {
            background: #000;
            color: #ffffff;
            border: none;
            width: 30px;
            height: 30px;
            float: right;
        }

        #close-alert-panel:hover {
            background: #f00;
        }
    </style>

    <!--javascript-->
    <script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>

<div id="app">
    <!-- 當(dāng)點擊button的時候,顯示模態(tài)框,在模態(tài)框中點擊關(guān)閉按鈕時,關(guān)閉模態(tài)框 -->
    <button id="btn" @click="showDialog">點擊登陸</button>

    <modal :is-hide-dialog="!isHide" @close="closeModal"></modal>
</div>

<template id="dialog">
    <div id="alert-panel" v-show="isHideDialog">
        <div id="login">
            <button id="close-alert-panel" @click="$emit('close')">&times;</button>
        </div>
    </div>
</template>

<script>
    // 聲明一個組件
    let modal = Vue.extend({
        template: '#dialog',
        props: ["isHideDialog"],
    });

    const vm = new Vue({
        el: '#app',
        data: {
            isHide: true,
        },
        methods: {
            showDialog() {
                this.isHide = false;
            },
            closeModal() {
                this.isHide = true;
            }
        },
        components: {
            'modal': modal
        }
    });
</script>
</body>
</html>
  • 父組件調(diào)用子組件的方法

注: 如果ref放在組件上,那么通過$refs拿到的不是組件的dom而是這個組件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue study</title>
    <script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>

<div id="app">
    <!-- 注: 如果ref放在組件上,那么通過$refs拿到的不是組件的dom而是這個組件 -->
    <load ref="load"></load>
</div>

<!--templates-->
<template id="load">
    <div v-if="isShow">
        <p>玩命加載中...</p>
    </div>
</template>

<!-- JavaScript -->
<script>
    let load = Vue.extend({
        template: '#load',
        data () {
            return {
                isShow: true,
            }
        },
        methods: {
            hide(){
                this.isShow = false;
                console.log("我被調(diào)用了,這個組件已經(jīng)被隱藏了");
            }
        },
    });

    const vm = new Vue({
        el: '#app',
        components: {
            "load": load,
        },
        mounted () {
            // 當(dāng)vm實例掛載的時候,就調(diào)用子組件的方法,隱藏加載組件
            this.$refs.load.hide();
        }
    });

</script>
</body>
</html>

  • 在子組件中加工父組件傳遞的值

默認(rèn)在子組件中不能修改父組件傳遞的值,如果非要
加工父組件傳遞過來的數(shù)據(jù),可以使用 computed 屬性或者 data()
來加工父組件傳遞的值,此種方式雖然能夠加工了父組件
傳遞的數(shù)據(jù),但是不會改變父組件的數(shù)據(jù),保證了各個組件的獨立性(單向數(shù)據(jù)流)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue study</title>
    <script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>


<div id="app">
    <my-comp :name="message"></my-comp>
</div>

<!--templates-->
<template id="my">
    <div>
        <p>父組件原數(shù)據(jù): {{name}}</p>
        <p>改變后的數(shù)據(jù): {{myName}}</p>
        <p>改變后的數(shù)據(jù): {{myName2}}</p>
    </div>
</template>

<!-- JavaScript -->
<script>
    // make a component
    let myComponent = Vue.extend({
        template: '#my',
        props: ["name"],
        // 要求: 在子組件中,將父組件傳遞的值拼接一個隨機數(shù)
        // 方式一:使用計算屬性來改變父組件傳遞的值
        computed:{
            myName(){
                return this.name + Math.random();
            }
        },
        // 方式二:使用data()方法來改變父組件傳遞的值(局部變量)
        data(){
            return {
                "myName2" :this.name + Math.random(),
            }
        },
    });

    const vm = new Vue({
        el: '#app',
        data: {
            message: 'hello world',
        },
        components: {
            // register a local component
            "my-comp": myComponent,
        },
    });

</script>
</body>
</html>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市红且,隨后出現(xiàn)的幾起案子磁滚,更是在濱河造成了極大的恐慌,老刑警劉巖委刘,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慨亲,死亡現(xiàn)場離奇詭異混槐,居然都是意外死亡戈锻,警方通過查閱死者的電腦和手機歼跟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來格遭,“玉大人哈街,你說我怎么就攤上這事【苎福” “怎么了叹卷?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坪它。 經(jīng)常有香客問我,道長帝牡,這世上最難降的妖魔是什么往毡? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮靶溜,結(jié)果婚禮上开瞭,老公的妹妹穿的比我還像新娘唆鸡。我一直安慰自己点把,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布巷波。 她就那樣靜靜地躺著瓷炮,像睡著了一般葱色。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上娘香,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天苍狰,我揣著相機與錄音,去河邊找鬼烘绽。 笑死淋昭,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的安接。 我是一名探鬼主播翔忽,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了歇式?” 一聲冷哼從身側(cè)響起驶悟,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贬丛,沒想到半個月后撩银,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡豺憔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年额获,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恭应。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡抄邀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昼榛,到底是詐尸還是另有隱情境肾,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布胆屿,位于F島的核電站奥喻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏非迹。R本人自食惡果不足惜环鲤,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望憎兽。 院中可真熱鬧冷离,春花似錦、人聲如沸纯命。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亿汞。三九已至瞭空,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間留夜,已是汗流浹背匙铡。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碍粥,地道東北人鳖眼。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像嚼摩,于是被迫代替她去往敵國和親钦讳。 傳聞我的和親對象是個殘疾皇子矿瘦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 前言 您將在本文當(dāng)中了解到,往網(wǎng)頁中添加數(shù)據(jù),從傳統(tǒng)的dom操作過渡到數(shù)據(jù)層操作,實現(xiàn)同一個目標(biāo),兩種不同的方式....
    itclanCoder閱讀 25,746評論 1 12
  • 組件是可復(fù)用的Vue實例,且?guī)в幸粋€名字愿卒。我們可以在一個通過new Vue創(chuàng)建的Vue根實例中缚去,把這個組件作為自定...
    oWSQo閱讀 325評論 0 0
  • 祭出demo 基礎(chǔ)示例 組件是可復(fù)用的 Vue 實例,所以它們與 new Vue 接收相同的選項琼开,例如 data易结、...
    rainbowboy閱讀 850評論 0 50
  • 組件(Component)是Vue.js最核心的功能,也是整個架構(gòu)設(shè)計最精彩的地方柜候,當(dāng)然也是最難掌握的搞动。...
    六個周閱讀 5,582評論 0 32
  • 冰凌...
    晨曦山人閱讀 183評論 0 1