vue組件原生事件以及路由

1.組件

組件就是能夠擴展HTML元素,封裝可重用的HTML代碼,能夠將組件看做自定義的HTML元素html

1.1組件註冊

全局註冊:vue

組件註冊時,須要給他一個名字,以下:python

Vue.component('my-component-name', { /* ... */ })

# 組件名使用kebab-case (短橫線分隔命名)定義時,引用這個元素時使用 <my-component-name>ajax

# 組件名使用 PascalCase (駝峯式命名) 定義時,引用這個元素時使用<my-component-name> 和 <MyComponentName>均可以vue-router

局部註冊:數組

經過一個普通的 JavaScript 對象來定義組件app

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }

而後在component選項中定義想要的組件異步

new Vue({
  el: '#app'
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

# 局部註冊的組件在其子組件中不可用ide

全局註冊實例:函數

組件的複用(主體代碼):

<body>
    <div id="app">
        <buttons></buttons>
        <buttons></buttons>
        <buttons></buttons>
    </div>
    <hr>
    <div id="app2">
        <buttons></buttons>
    </div>
</body>
<script>
    // 組件中data必須是一個函數,第一個參數是咱們的定義標籤
    Vue.component('buttons',{
        data:function(){
            return{
                count:0
            }
        },
        template:`<button v-on:click='count++'>biubiubiu{{ count }}</button>`
    })

    var app = new Vue({
        el:"#app"
    })

    var app2 = new Vue({
        el:"#app2"
    })
</script>

效果:

局部註冊實例:

(父組件往子組件傳值)

<body>
    <div id="app">
        <bts v-bind:name='fir'></bts>    
        <bts v-bind:name='sec'></bts>    
        <bts v-bind:name='thi'></bts>    
        <hr>
        <bts v-for='nums in list' v-bind:name='nums'></bts>
    </div>
</body>
<script>
    // 這裏的buttons屬於咱們的自定義標籤,經過props向子組件傳遞數據
    var myComponent = {
        template:`<button v-on:click="cli">{{name}}+{{count}}</button>`,
    // 使用props聲明,組件須要外邊從data給傳一個字符串格式的name變量
 props:{
            name:String
        },    
        data:function(){
            return{
                count:0,
            }
        },
        methods:{
            cli:function(){
                this.count += 1
            }
        }
    }

    // 自定義局部組件
    new Vue({
        el:'#app',
        data:{
            list:[
            '1',
            '2',
            '3',
            ],
            fir:'first',
            sec:'second',
            thi:'third',
        },
        components:{
            bts:myComponent    
        }
    })
</script>

效果:

1.2props

官網連接

2.組件組織:

該圖很好的代表了組件的組織關係對應圖,或者說是層級關係

Vue.js經過組件,把一個單頁應用中的各類模塊拆分到一個一個單獨的組件(component)中,只要先在父級應用中寫好各類組件標籤,而且在組件標籤中寫好要傳入組件的參數(就像給函數傳入參數同樣,這個參數叫作組件的屬性),而後再分別寫好各類組件的實現,而後整個應用就算作完了

3.組件中的數據傳遞(props)

<body>
    <div id="app">
        <!-- 寫死了 -->
        <buttons title="My journey with Vue"></buttons>
        <buttons title="Blogging with Vue"></buttons>        
    </div>
    <hr>
    <!-- 動態傳遞 -->
    <div id="app2">
        <buttons
        v-for="post in posts"
          v-bind:key="post.id"
          v-bind:title="post.title"
        ></buttons>
    </div>
</body>
<script>
    Vue.component('buttons', {
              props: ['title'],
              template: '<h3>{{ title }}</h3>'
    })

    var app = new Vue({
        el:"#app",
    })

    var app2 = new Vue({
        el:"#app2",
        // 動態傳遞一個數組
        data: {
        posts: [
              { id: 1, title: 'My journey with Vue' },
              { id: 2, title: 'Blogging with Vue' },
            ]
      }
    })
</script>

 子組件往父組件傳值:

<body>
    <div id="app">
        <p>總數:{{total}}</p>
        <bts v-for='nums in list' v-bind:name='nums' v-on:zhi="add"></bts>
    </div>
</body>
<script>
    // 這裏的bts屬於咱們的自定義標籤,經過props向子組件傳遞數據
    var myComponent = {
        template:`
        <div>
        <button v-on:click="cli">{{count}}{{name}}</button>       
        </div>
        `,
    // 使用props聲明,組件須要外邊從data給傳一個字符串格式的name變量
        props:{
            name:String
        },    
        data:function(){
            return{
                count:0,
            }
        },
        methods:{
            cli:function(){
                this.count += 1;
            // 在組件中經過觸發自定義事件向外傳遞信息
            this.$emit('zhi')
            }
        }
    }

    // 自定義局部組件
    new Vue({
        el:'#app',
        data:{
            total:0,
            list:[
            '只豬','只狗','只兔子',
            ]    
        },
        components:{
            bts:myComponent    
        },
        methods:{
            add:function(){
                this.total += 1
            }
        }
    })
</script>

效果:

組件間傳值(生成一個空vue對象bus):

各個組件內部要傳輸的數據或者要執行的命令信息,靠bus來通訊。

<body>
<div id="app">
    <bt></bt>
    <hr>
    <nums></nums>
</div>

</body>
<script>
    var bus = new Vue();
    var app = new Vue({
        el:'#app',
        data:{
            name:'bt'
        },
        components:{
            bt:{
                template:`<button v-on:click='check'>點我</button>`,
                methods:{
            check(){
                bus.$emit('things')
            }
        }
    },
        nums:{
            template:`<div>{{num}}</div>`,
            data:function(){
                return {
                    num: 0
                }
                
            },
            mounted:function(){
                // 該組件中this指num實例
                var _this = this;
                console.log(_this);
                // 監聽bus
                bus.$on('things', function(){
                        // 在這個做用域中 this 指的是 bus
                        console.log(this.num)  // undefined
                        // 修改num組件中的num值
                        // 此時this是誰?
                        // this.num += 1;  // 有問題
                        _this.num += 1;
                    })
                }

            }
        }
        
    })
</script>

在第一個組件中的methods方法裏,經過bus.$emit()方法發射事務

在第二個組件實例化的鉤子中(mounted)中,經過bus.$on監聽自家$emit觸發的事件

4.插槽:(使用自定義標籤<slot>元素達到目的的)

官網連接

插槽是佔位置的!!!
插槽多了能夠起名字,進行區分! --> <span slot='heihei'>嘿嘿!</span>

<body>
    <div id="app">
        <alert-box>
            Something bad happened.
        </alert-box>
    </div>
</body>
<script>
    Vue.component('alert-box', {
        template: `
        <div class="demo-alert-box">
        <strong>Error!</strong>
        <slot></slot>
        </div>
        `
    })
    new Vue({
        el:"#app"
    })    
</script>

效果:

5.將原生事件綁定到組件(.naive修飾符)

  若是想在一個組件的根元素上直接監聽一個原生事件,這時候就可使用v-on的.naive修飾符

實例0(不推薦使用):

<body>
<div id="app">
    <ztzsb v-on:click='hehe'></ztzsb>
</div>
</body>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            name: 'ztz',
            age: 24
        },
        components: {
            ztzsb: {
                template: `<button v-on:click='shangkele'>趙天柱 逃課!</button>`,
                methods:{
                    shangkele:function(){
                        this.$emit('click')
                    }
                }
            }
        },
        methods:{
            hehe:function(){
                alert(123);
            }
        }
    })
</script>
</html>

實例1:

<body>
    <div id="app">
        <ztz v-on:click.native='hehe'></ztz>
    </div>
</body>
<script>
    var app = new Vue({
        el:"#app",
        data:{},

        components:{
            ztz:{
                template:`<button>趙天柱 逃課!</button>`
            },
        },
        methods:{
            hehe:function(){
                alert(123);
            }
        }
    })
</script>
</html>

再看看下面的實例2:

<body>
    <div id="app">
        <ztz></ztz>
    </div>
</body>
<script>
    var app = new Vue({
        el:"#app",
        data:{},
        components:{
            ztz:{
                template:`<button v-on:click='hehe'>趙天柱 逃課!</button>`,
                methods:{
                    hehe(){
                        alert(123);
                    }
                }
            },    
        }
    })
</script>

## 實例1和2二者效果如出一轍,一個是在根元素上進行事件綁定,一個是在局部組件上進行綁定  

6.總結

1. Vue組件
0. 組件注意事項!!!
	data屬性必須是一個函數!

1. 註冊全局組件
	Vue.component('組件名',{
		template: ``
	})
	
	var app = new Vue({
		el: '#app'
	})
2. 註冊局部組件
	var app = new Vue({
		el: '#app',
		components:{
			局部組件名:{
				template: `...`
			}
		}
	})
3. 傳值
	1. 父組件 --> 子組件
		1. 父組件經過 v-bind:變量='值'
		2. 子組件須要經過props 聲明我須要的變量
	2. 子組件 --> 父組件
		子組件經過觸發自定義事件的方式向外傳遞信息
		1. 子組件: this.$emit('自定義事件')
		2. 父組件: v-on:自定義事件='方法名'
		
	3. 組件間傳值
		1. 補充:Vue實例的生命週期鉤子函數(共8個)
			1. beforeCreate    --> 數據屬性聲明但沒有賦值
			2. created         --> 數據屬性賦值
			3. beforeMount     --> 頁面上的 {{name}} 尚未被渲染
			4. mounted         --> 頁面上的 {{name}} 被替換成真正的內容
			...
			
		2. 基於bus對象實現
	
4. 插槽(slot)
	插槽是佔位置的!!!
	插槽多了能夠起名字,進行區分!   --> <span slot='heihei'>嘿嘿!</span>
	<alert>根本不顯示</alert>
	
		
5. 組件的注意事項:
	1. 特殊的組件須要使用is語法聲明一下 好比 table、select、ul等內部使用的組件
	2. 捕獲子組件的原生事件

7.Vue.Router

  Vue Router 是 Vue.js 官方的路由管理器

  將組件 (components) 映射到路由 (routes),而後告訴 Vue Router 在哪裏渲染它們,實現異步ajax界面切換效果(頁面不刷新)

# 例,注意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>
<body>
	<div id="app">
		<!-- 路由入口 -->
		<router-link to='/index'>index頁面</router-link>	
		<router-link to='/home'>home頁面</router-link>
		<hr>
		<!-- 路由出口 -->
		<router-view></router-view>	
	</div>
</body>
	<script>
		// 路由,數組包含兩個路由
		const routess = [
		{path:'/index',component:{template:`<div><h2>index頁面</h2></div>`}},
		{path:'/home',component:{template:`<div><h2>home頁面</h2></div>`}},
		]
		// 生成實例,routes是關鍵字,它的值必須是一個數組
		const routerObj = new VueRouter({
			routes:routess
		})

		new Vue({
			el:'#app',
			// 路由實例掛載到vue實例中,router是關鍵字
			router:routerObj
		})
	</script>  
</body>
</html>

 效果:

7.1路由動態匹配 

咱們有一個 User 組件,對於 ID 各不相同的用戶,都要使用這個組件來渲染。那麼,咱們能夠在 vue-router 的路由路徑中使用「動態路徑參數」(dynamic segment) 來達到這個目的

一個「路徑參數」使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到 this.$route.params,以下

 

實例:

<body>
<div id="app">
    <!--路由的入口-->
    <!-- 使用 router-link 組件來導航. -->
    <!-- 經過傳入 `to` 屬性指定連接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
    <router-link to="/user/index">index頁面</router-link>
    <router-link to="/user/home">home頁面</router-link>
    <hr>
    <p>666</p>
    <!--路由的出口-->
    <!-- 路由匹配到的組件將渲染在這裏 -->
    <router-view></router-view>
    <p>999</p>
</div>
<script>
    //寫路由
    const routeArray = [
        { path: '/user/:name',
            component: {template: `<h3>這是{{$route.params.name}}的主頁頁面!</h3>`}
        }
    ]
    //生成路由實例
    const routerObj = new VueRouter({
        routes: routeArray
    })
    var app = new Vue({
        el:'#app',
        //router是關鍵字,它的值必須是數組
        router:routerObj  //將路由實例掛載到vue實例中
    })
</script> 

  效果:

7.2嵌套路由(子路由)

 URL 中各段動態路徑按某種結構對應嵌套的各層組件,以下:

  

實例(關鍵點在於使用append拼接路由):

<div id="app">
    <router-link to="/user/index">index</router-link>
    <router-link to="/user/home">home</router-link>
    <hr>
    <router-view></router-view>
</div>
<script>
	// 生成路由數組
    const routeArray = [
        {
            path: '/user/:name',
            component: {
                //append表示當前路由拼接url,好比/user/home/info
                //router-view對應子路由的template的內容
                template: `<div>
                    <h3>這是{{$route.params.name}}的主頁頁面!</h3>
                    <hr>
                    <router-link to='info' append>用戶詳細信息</router-link>
                    <router-view></router-view>
                </div>`
            },
            // 定義子路由
            children:[
                {
                    path: 'info',
                    component:{
                        template: `
                            <div>
                                <h1>大傻逼</h1>
                            </div>
                        `
                    }
                },
            ]
        }
    ]
    //生成VueRouter實例
    const routerObj = new VueRouter({
        //routes是關鍵字參數,它必須對應一個數組
        routes: routeArray
    })
    var app = new Vue({
        el:'#app',
        data:{},
        //router是關鍵字,它的值必須是數組
        router:routerObj  //將路由實例掛載到vue實例中
    })
</script>

效果:

總結:

1. Vue全家桶
	Vue + VueRouter + VueX
2. VueRouter  https://router.vuejs.org/zh/
	1. 基本使用
		1. 必須導入vue-router.js文件
		2. 要有VueRouter()實例
		3. 要把VueRouter實例掛載到Vue實例中
		
		4. 路由的入口
			<router-link to='/index'>index頁面</router-link>
		5. 路由的出口
			<router-view></router-view>
	2. 路由的參數
		1. path: '/user/:name' --> 匹配路由
		$route.params.name     --> 取值
		
		2. /user/alex?age=9000 --> url中攜帶參數
		$route.query.age       --> 取出url的參數
		
	3. 子路由
		children:[
			{
				path: '',
				component: {
					template: `...`
				}
			}
		]
		
		<router-link to='info' append></router-link>
相關文章
相關標籤/搜索