vue 基礎 進階教程(3):組件嵌套、組件之間的通信、路由機制、slot傳值

前面的nodejs教程並沒有停止更新,因爲node項目需要用vue來實現界面部分,所以先插入一個vue教程,以免不會的同學不能很好的完成項目。

本教程,將從零開始,教給大家vue的基礎、高級操作、組件封裝等,再配合前面的Nodejs後臺,實現一個完整的項目。

 

組件嵌套


 

在組件中使用components定義子組件,可以定義多個,定義好以後,就可以在組件的模板中使用子組件了。看下面示例:具體解釋在註釋中

 

複製代碼

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

<div id="box">
    <aaa></aaa>
</div>

<!--模板可以使用 template標籤寫到外面,然後在 componets裏面調用-->
<template id="temA">  
    <div>
        <h3>我是:{{msg}}</h3>
        <bbb></bbb>  <!-- 調用子組件 -->
    </div>
</template>

<script>
    var vm=new Vue({
        el:'#box',
        components:{
            'aaa':{
                data:function(){
                    return{
                        msg:'父組件'
                    }
                },
                methods:{
                    test:function(){
                        alert("我是父組件")
                    }
                },
                template:'#temA',/*父組件的模板*/
                components:{
                    'bbb':{
                        template:"<h3>我是子組件</h3>"
                    }
                }
            }
        }
    })
</script>
</body>
</html>

複製代碼

 

 

 

 

 

父子組件之間的通信

使用 v-bind:  (或直接用冒號) 傳遞數據,使用props接收數據,先看如下代碼

複製代碼

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

<div id="box">
    <aaa></aaa> <!--父組件的調用-->
</div>

<template id="temA">  <!--模板可以使用 template標籤寫到外面,然後在 componets裏面調用-->
    <div>
        <h3>我是:{{msg}},子集顯示 ==>{{msg2.text}}</h3>
        <bbb :m1="msg1" :m2="msg2"></bbb>   <!--調用子組件,使用  :鍵名=值(對應父組件data中的值)  去傳參數-->
    </div>
</template>

<script>
    var vm=new Vue({
        el:'#box',
        components:{
            'aaa':{
                data:function(){
                    return{
                        msg:'父組件',
                        msg1:"父級的共享數據1",
                        msg2:{             /*父組件往子組件傳的一般只不能子集修改,只有傳對象格式,子集中就可以修改了,父組件也同時改了*/
                            text:"父級的共享數據2",
                            style:{
                                height:"100px",
                                background:"orange"
                            }
                        }
                    }
                },
                methods:{
                    test:function(){
                        console.log("父組件的方法已調用");
                    }
                },
                template:'#temA',/*當前組件裏調用子組件*/
                components:{
                    'bbb':{
                        props:["m1","m2"],   /* 需要使用的數據,使用數組參入 ,和函數的形參很像,然後在調用的地方使用 v-bind傳入 */
                        template:"<div><h3 @click='showMsg'>我是bbb組件,我使用的父級數據 ==>{{m1}},{{m2.text}} </h3></div>",
                        methods:{
                            showMsg:function(){
                                this.m2.text = "值被子組件修改了";
                                this.$parent.test();
                            }
                        }

                    }
                }
            }
        }
    })
</script>
</body>
</html>

複製代碼

解釋一下數據的傳遞流程(以msg2爲例):在父組件中的數據中有個msg2數據,在模板中調用子組件的時候 以名爲 m2 傳遞給了子組件 ,然後在子組件中就可以通過props接收到,這樣在子組件中就可以使用變量 this.m2訪問到 父組件的 msg2對應的值了。(如果傳的值是對象,則傳遞引用指針,如果傳遞的是基本類型,則直接將值傳遞過去)

運行:

當點擊子組件的h3標籤,觸發子組件的showMsg方法,在方法中,我們通過 this.m2.text改變了父級的msg2.text的值。通過  this.$parent.方法名    可以直接訪問父組件裏的方法。

點擊bbb後

 

 


 

非父子組件之間的通信

上面我們使用props只能解決父子組件之間的通信,當兩個兄弟關係的組件,就不能這樣傳遞了

兄弟節點之間需要使用 事件的觸發方法 $emit去實現

先看代碼:具體解釋在註釋中

代碼中,我們聲明瞭一個獨立的空Vue公用實例,用來觸發通訊的事件。在a組件中使用 $emit觸發事件,在 c組件中使用on監聽事件,就可以實現數據的傳遞了。

複製代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
   <div id="box">
       <com-a></com-a> <!-- 調用com-a組件 -->
       <com-c></com-c><!-- 調用com-c組件 -->
   </div>
<script>
   var Event=new Vue();  // 聲明一個獨立的空Vue公用實例,用來觸發通訊的事件

    var a={
        template:'<div><span>我是a組件,我的數據內容是{{msga}}</span><br><input type="button" value="我要發送數據" @click="send"></div>',
        data(){
            return{
             msga:'我是a數據,我要發送給兄弟組件'
            }
        },
        methods:{
            send(){
                Event.$emit('a-msg',this.msga)  //觸發前面 Event 公用示例的方法,那麼別的地方就可以想辦法監聽接收這個事件。參數(事件名,傳輸的值)
            }
        }
    };
    var c={
        template:"<div><h3>這是C組件</h3><span>我從A裏面接受的數據:{{a}}</span></div>",
        data(){
            return{
                a:''
            }
        },
        mounted(){    //這裏的mouted表示當組件和頁面掛載完成的時候,需要執行的函數
            var _this = this;  //因爲在Event.on內部的this是指向 Event實例的,所以這裏,先使用 _this將this存起來,後面就可以使用了。
            Event.$on('a-msg',function (a) {  //使用on監聽事件 a-msg,這樣當a組件中使用 emit主動觸發了 Event實例的a-msg事件之後,這裏就可以接收到
                alert('觸發了接收');
                _this.a = a;
            })
        }
    };
    new Vue({
        el:'#box',
        components:{
            'com-a':a,
            'com-c':c
        }
    })


</script>

</body>
</html>

複製代碼

 

 當點擊發送數據按鈕,數據就傳輸給了c組件。


路由


 

 路由可以讓我們在頁面中加載不同的模板內容,

使用vue的路由,需要藉助vue-router.js

    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

 

我們使用路由配置一個tab切換,點擊首頁和列表分別顯示不同內容,並且點擊的時候,url中的路徑會發生對應的改變。

 

代碼如下:代碼解釋在註釋中。

複製代碼

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
    <div id="box">
        <div>
            <router-link to="/home">首頁</router-link> <!-- 會被vue識別,自動顯示成a標籤-->
            <router-link to="/List">列表</router-link> <!-- 會被vue識別,自動顯示成a標籤-->
        </div>
        <div>
            <router-view></router-view>    <!-- 點擊上面的link標籤由,需要顯示模板的地方 -->
        </div>
    </div>
</body>
<script>
    /*組件*/
    var Home = {
        template:"<h3>我是主頁的內容</h3>"
    };
    var List = {
        template:"<h3>我是文章列表</h3>"
    };

    //配置路由
    var routerArr=[
        {
            path:"/home", /* router-link 的 to跳轉的地址 */
            component:Home  /* 路徑對應的組件 */
        },
        {
            path:"/List", /* router-link 的 to跳轉的地址 */
            component:List  /* 路徑對應的組件 */
        },
        {path:"*",component:Home}  /*其他的所有情況,都跳轉到首頁*/
    ];

    //生成路由示例
    var router= new VueRouter({
        routes:routerArr
    });

    //vue實例
    var vm=new Vue({
        el:'#box',
        data:{},
        /* 示例掛載路由 */
        router:router
    })
</script>
</html>

複製代碼

 

 

二級路由:具體解釋在註釋中

注:

二級路由使用children來配置 ,內部配置和一級路由一樣

tab切換中的當前選項標籤會自動添加 router-link-active類,我們只需要設置該類的樣式,就可以實現當前選中的樣式了。

複製代碼

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        body{
            padding: 30px;
        }
        ul, li{
            display: inline-block;
            list-style: none;
        }
        #box a{
            text-decoration: none;
            color: #2479dc;
            padding: 5px 15px;
        }
        #box .router-link-active{
            background: #2479dc;
            color: #fff;
        }
    </style>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
    <div id="box">
        <div>
            <router-link to="/home">首頁</router-link> <!-- 會被vue識別,自動顯示成a標籤-->
            <router-link to="/List">列表</router-link>
            <router-link to="/users">用戶</router-link>
        </div>
        <div>
            <router-view></router-view>    <!-- 點擊上面的link標籤由,需要顯示模板的地方 -->
        </div>
    </div>

    <!-- 模板 temUser -->
    <template id="temUser">
        <div>

            <h3>用戶信息</h3>
            <hr/>
            <ul>
                <li><router-link to="/users/xiaoming">小明</router-link></li>
                <li><router-link to="/users/xiaohong">小紅</router-link></li>
            </ul>
            <div>
                <router-view></router-view>    <!-- 點擊上面的link標籤由,需要顯示模板的地方 -->
            </div>
        </div>
    </template>

</body>
<script>
    /*組件*/
    var Home = {
        template:"<h3>我是主頁的內容</h3>"
    };
    var List = {
        template:"<h3>我是文章列表</h3>"
    };
    //用戶
    var users = {
        template:"#temUser"
    };

    var xiaoming = {
        template:"<h3>我是小明</h3>"
    }
    var xiaohong = {
        template:"<h3>我是小紅</h3>"
    }

    //配置路由
    var routerArr=[
        {
            path:"/home", /* router-link 的 to跳轉的地址 */
            component:Home  /* 路徑對應的組件 */
        },
        {
            path:"/List", /* router-link 的 to跳轉的地址 */
            component:List  /* 路徑對應的組件 */
        },
        {
            path:"/users", /* router-link 的 to跳轉的地址 */
            component:users,  /* 重定向到首頁 */
            children:[        /* 二級路由使用children來配置 ,內部配置和一級路由一樣 */
                {path:"xiaoming",component:xiaoming},
                {path:"xiaohong",component:xiaohong}
            ]
        },
        {path:"*",component:Home}  /*其他的所有情況,都跳轉到首頁*/
    ];

    //生成路由示例
    var router= new VueRouter({
        routes:routerArr
    });

    var vm=new Vue({
        el:'#box',
        data:{},
        /* 示例掛載路由 */
        router:router
    })
</script>
</html>

複製代碼

 

 

 


 url參數傳遞


 在配置路由的時候,路徑名前面加 冒號,就表示此路徑爲參數

然後在模板中就可以使用 $route.params去訪問到這個值了

 

完整示例代碼如下:

複製代碼

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        body{
            padding: 30px;
        }
        ul, li{
            display: inline-block;
            list-style: none;
        }
        #box a{
            text-decoration: none;
            color: #2479dc;
            padding: 5px 15px;
        }
        #box .router-link-active{
            background: #2479dc;
            color: #fff;
        }
    </style>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
    <div id="box">
        <div>
            <router-link to="/home">首頁</router-link> <!-- 會被vue識別,自動顯示成a標籤-->
            <router-link to="/List">列表</router-link>
            <router-link to="/users">用戶</router-link>
        </div>
        <div>
            <router-view></router-view>    <!-- 點擊上面的link標籤由,需要顯示的內容 -->
        </div>
    </div>

    <template id="temUser">
        <div>

            <h3>用戶信息</h3>
            <hr/>
            <ul>
                <li><router-link to="/users/2/xiaoming/哈哈">小明</router-link></li>
                <li><router-link to="/users/xiaohong/15">小紅</router-link></li>
            </ul>
            <div>
                <router-view></router-view>    <!-- 點擊上面的link標籤由,需要顯示的內容 -->
            </div>
        </div>
    </template>

</body>
<script>
    /*組件*/
    var Home = {
        template:"<h3>我是主頁的內容</h3>"
    };
    var List = {
        template:"<h3>我是文章列表</h3>"
    };
    //用戶
    var users = {
        template:"#temUser"
    };

    var xiaoming = {
        template:"<h3>我是小明-{{$route.params.sysId}}{{$route.params.Id}}</h3>"
    }
    var xiaohong = {
        template:"<h3>我是小紅-{{$route.params.sysId}}</h3>"
    }

    //配置路由
    var routerArr=[
        {
            path:"/home", /* router-link 的 to跳轉的地址 */
            component:Home  /* 路徑對應的組件 */
        },
        {
            path:"/List", /* router-link 的 to跳轉的地址 */
            component:List  /* 路徑對應的組件 */
        },
        {
            path:"/users", /* router-link 的 to跳轉的地址 */
            component:users,  /* 重定向到首頁 */
            children:[
                {path:":Id/xiaoming/:sysId",component:xiaoming},
                {path:"xiaohong/:sysId",component:xiaohong}
            ]
        },
        {path:"*",component:Home}  /*其他的所有情況,都跳轉到首頁*/
    ];

    //生成路由示例
    var router= new VueRouter({
        routes:routerArr
    });

    var vm=new Vue({
        el:'#box',
        data:{},
        /* 示例掛載路由 */
        router:router
    })
</script>
</html>

複製代碼

 點擊  用戶 -->  小紅 ,然後可以看到我們url中的 "15",就傳遞到了模板中顯示出來了。

 

 

 

補充講一個概念:槽/slot      用來接收標調用時傳入的內部內容

直接上代碼,解釋在註釋中

複製代碼

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body{
            line-height: 30px;
            padding: 10px;
        }
    </style>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>

<div id="box">
    <who-h>
        <p>插入slot的值</p>  <!--  在組件調用的時候,標籤內部的內容,會被放到template中定義的槽slot標籤中 -->
        <ul>
            <li>ssss</li>
            <li>ssss</li>
            <li>ssss</li>
        </ul>
    </who-h>
</div>

<template id="temp01">  <!-- template 用來定義模板,需要指定一個id -->
    <div>               <!--  模板中的內容,只能包裹在唯一一個標籤中  (最外層不能有多個標籤) -->
        <h3>{{msg}}</h3>
        <slot></slot>  <!-- 用來接收標調用時傳入的內部內容-->
    </div>

</template>

<script>

    var item = Vue.extend({
        data:function(){
            return {
                msg:"示例的值"
            }
        },
        template:'#temp01'
    });

    var vm = new Vue({
        el:"#box",
        data:{},
        components:{  //可以配置多個內部組件
            "who-h":item    //組件命名的時候,最好都用引號引起來(當然,單個單詞的時候不用也不報錯)
        }
    })
    
</script>

</body>
</html>

複製代碼

 顯示結果我們可以看到,原來 slot所在的地方被傳入的p和ul標籤替代了

 

上面是一個slot的情況,當如果我們要多個slot分開傳值,我們就需要給slot指定名字,並且給傳入的標籤指定slot

示例如下:具體的解釋在註釋中

複製代碼

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body{
            line-height: 30px;
            padding: 10px;
        }
    </style>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>

<div id="box">
    <who-h>
        <p slot="slot01">插入slot的值1(p)</p>  <!--  在組件調用的時候,標籤內部的內容,會被放到template中定義的槽slot標籤中,使用slot屬性去指定插入哪個slot,如果不指定slot名,就插入沒有名字的slot中 -->
        <ul slot="slot02">
            <li>插入slot的值2(ul)</li>
        </ul>
        <span>插入slot的值3(span)</span>
    </who-h>
</div>

<template id="temp01">  <!-- template 用來定義模板,需要指定一個id -->
    <div>               <!--  模板中的內容,只能包裹在唯一一個標籤中  (最外層不能有多個標籤) -->
        <h3>{{msg}}</h3>
        <slot></slot>  <!-- 用來接收標調用時傳入的內部內容-->
        <slot name="slot01"></slot>
        <slot name="slot02"></slot>
    </div>

</template>

<script>

    var item = Vue.extend({
        data:function(){
            return {
                msg:"示例的值"
            }
        },
        template:'#temp01'
    });

    var vm = new Vue({
        el:"#box",
        data:{},
        components:{  //可以配置多個內部組件
            "who-h":item    //組件命名的時候,最好都用引號引起來(當然,單個單詞的時候不用也不報錯)
        }
    })
    
</script>

</body>
</html>

複製代碼

 

 結果如下,三個傳入的值 分別插入到了對應的位置

 

 

 

 

今天就講到這裏,vue就講這麼多,下次更新的時候,就是vue+nodejs的項目了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章