vue.js 模板 看着官方文檔學習 含部分小demo

Vue組件基本示例

組件是可複用的實例,且帶有一個名字,下面的例子中,button-counter就是一個實例.咱們能夠在一個經過 new Vue 建立的 Vue 根實例中,把這個組件做爲自定義元素來使用
由於組件是可複用的 Vue 實例,因此它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命週期鉤子等。僅有的例外是像 el 這樣根實例特有的選項。html

<div id="components-demo">
    <button-counter></button-counter>
</div>
Vue.component('button-counter',{
        data:function () {
            return{
                count:0
            }
        },
        template: '<button v-on:click="count++">You clicked me {**加粗文字**{count}}times</button>'
    })
    new Vue({
        el:'#components-demo'
    })
注意:要先註冊組件(Vue.component),再建立vue的實例,不然會出現如下的報錯:
vue.js:634 [Vue warn]: Unknown custom element: <button-counter> - did you register the component correctly? For recursive components, make sure to provide the "name" option.(found in <Root>)

一個組件的 data 選項必須是一個函數,所以每一個實例能夠維護一份被返回對象的獨立的拷貝。用一次組件,就會有一個它的新實例被建立

組件註冊

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

組件名 (W3C:字母全小寫且必須包含一個連字符)
組件名定義方式有兩種:使用 kebab-case或 PascalCase
也就是說 <my-component-name> 和 <MyComponentName> 都是可接受的。vue

組件註冊分爲全局註冊和局部註冊npm

全局註冊

全局註冊的組件能夠用在其被註冊以後的任何 (經過 new Vue) 新建立的 Vue 根實例,也包括其組件樹中的全部子組件的模板中。數組

<div id="global">
    <component-a></component-a>
    <component-b></component-b>
    <component-c></component-c>
</div>
 Vue.component('component-a',{
        data:function () {
            return{
                clicked:0
            }
        },
        template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
    })
    Vue.component('component-b',{
        data:function () {
            return{
                clicked:0
            }
        },
        template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
    })
    Vue.component('component-c',{
        data:function () {
            return{
                clicked:0
            }
        },
        template:'<div><span>You have clicked</span><input type="button"  v-model="clicked" v-on:click="clicked++"><span>times.</span></div>'
    })
      new Vue({
        el:'#global'
    })

局部註冊

局部註冊的組件在其子組件不可用緩存

<div id="part">
    <component-a></component-a>
    <component-b></component-b>
    <component-c></component-c>
</div>
    var ComponentA = {
        data:function () {
            return {
                clicked:0
            }
        },
        template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
    }
    var ComponentB = {
        data:function () {
            return {
                clicked:0
            }
        },
        template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
    }
    var ComponentC = {
        data:function () {
            return {
                clicked:0
            }
        },
        template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
    }
   new Vue({
       el:'#part',

       components:{
          'component-a':ComponentA,
          'component-b':ComponentB,
          'component-c':ComponentC,
       }
   })

對於 components 對象中的每一個屬性來講,其屬性名就是自定義元素的名字,其屬性值就是這個組件的選項對象。app

經過 Prop 向子組件傳遞數據

Prop 是你能夠在組件上註冊的一些自定義特性。Prop 是你能夠在組件上註冊的一些自定義特性。一個組件默承認以擁有任意數量的 prop,任何值均可以傳遞給任何 prop。一個 prop 被註冊以後,你就能夠像這樣把數據做爲一個自定義特性傳遞進來異步

<div id="prop-demo">
    <blog-post title="prop just like data"></blog-post>
</div>
//給prop傳遞一個靜態值
<div id="blog-post-demo">
    <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title"></blog-post>
</div>
//給prop傳遞一個動態值
  Vue.component('blog-post', {
        props: ['likes','title'],
        template: '<div><strong>{{likes}}</strong><span>{{title}}</span></div>'
    })
    new Vue({
        el: '#prop-demo'
    })
    new Vue({
        el: '#blog-post-demo',
        data: {
            posts: [
                {likes:'1',title: 'My journey with Vue'},
                {likes:'2',title: 'Blogging with Vue'},
                {likes:'3',title: 'Why vue is so fun'}
            ]
        }
    })
<div id="blog-post-demo">
    <blog-post v-for="post in posts"  v-bind:post="post" v-bind:key="post.id" ></blog-post>
</div>
Vue.component('blog-post', {
        props: ['post'],
        template: '<div><span>{{post.title}}</span></div>'
   })
//接受一個單獨的 post prop
new Vue({
        el: '#blog-post-demo',
        data: {
            posts: [
                {id:'1',title: 'My journey with Vue'},
                {id:'2',title: 'Blogging with Vue'},
                {id:'3',title: 'Why vue is so fun'}
            ]
        }
    })

傳入一個數字:用 v-bind 綁定async

<blog-post v-bind:likes="42"></blog-post>

傳入一個布爾值:用 v-bind 綁定ide

<blog-post v-bind:is-published="false"></blog-post>

傳入一個數組:用 v-bind 綁定函數

<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>

傳入一個對象:用 v-bind 綁定

<blog-post
  v-bind:author="{
    name: 'Veronica',
    company: 'Veridian Dynamics'
  }"
></blog-post>

傳入一個對象的全部屬性:能夠用一個不帶參數的v-bind來綁定

<blog-post v-bind="post"></blog-post>
post: {
  id: 1,
  title: 'My Journey with Vue'
}

單項數據流
全部的 prop 都使得其父子 prop 之間造成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,可是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態。
額外的,每次父級組件發生更新時,子組件中全部的 prop 都將會刷新爲最新的值。這意味着你不該該在一個子組件內部改變 prop。

監聽子組件事件

<!--監聽子組件事件-->
<div id="blog-posts-events-demo">
    <div :style="{ fontSize: postFontSize + 'em' }">
        <blog-post
                v-for="post in posts"
                v-bind:key="post.id"
                v-bind:post="post"
                v-on:enlarge-text="postFontSize += 0.1"
        ></blog-post>
    </div>
</div>
    Vue.component('blog-post', {
        props: ['post'],
        template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <button v-on:click="$emit('enlarge-text')">
        Enlarge text
      </button>
      <div v-html="post.content"></div>
    </div>
  `
    })
    new Vue({
        el: '#blog-posts-events-demo',
        data: {
            posts: [{title:'I want to be bigger'}],
            postFontSize: 1
        }
    })

使用$emit拋出一個值,在組件上使用v-model

接受一個value屬性。再有新的value時觸發input事件

<!--在組件上使用v-model-->
<div id="model-demo">
    {{value}}
    <my-com v-model="value"></my-com>
    <button @click="valueMinus">-1</button>
</div>
    Vue.component('my-com', {
        props:{
            value:{
                type:Number
            }
        },
        template: '<div>{{currentValue}}<button @click="handleClick">+1</button></div>',
        data: function () {
            return {
                currentValue: this.value
            }
        },
        watch: {
            value(val) {
                this.currentValue = val;
            }
        },
        methods: {
            handleClick: function () {
                this.currentValue++;
                this.$emit('input', this.currentValue);
            }
        }
    })
    new Vue({
        el: '#model-demo',
        data: {
            value: 1
        },
        methods:{
            valueMinus:function () {
              return this.value--

        }
        }
    })

將原生的事件綁定到組件中,須要加上.native

.sync修飾符

clipboard.png

經過插槽分發內容

Slot是父組件與子組件的通信方式,能夠將父組件的內容顯示在子組件中。

demo實例

<div id="slot-demo">
    <say-to pname="Kayee">
        歡迎學習vue.js 的 組件之slot插槽。
    </say-to>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
    Vue.component('say-to',{
        props:['pname'],
        template:'<div>' +
            '您好<strong>{{pname}}</strong>' +
            '<slot></slot>' +
            '</div>'
    })
    new Vue({
        el:'#slot-demo',
    })
</script>

clipboard.png

Slot組合

<div id="slot-couple">
    <welcome a="嘉儀">
        <<span slot="Kayee">Kayee</span>
        <<span slot="Crystal">Crystal</span>
        <<span slot="Jiayi">Jiayi</span>
    </welcome>

</div>
  Vue.component('welcome',{
        props: ['a'],
        template: '<div>' +
            '<p>您好{{a}}</p>'+
            '<p>您好<slot name="Kayee"></slot> </p>'+
            '<p>您好<slot name="Crystal"></slot> </p>'+
            '<p>您好<slot name="Jiayi"></slot> </p>'+
                '</div>'
    })
    new Vue({
        el:'#slot-couple'
    })

clipboard.png

具名插槽

<div id="app">
    <base-layout>
        <template v-slot:header>
            This is hedaer.
        </template>
        <template v-slot:main>
            This is main.
        </template>
        <template v-slot:footer>
            This is footer.
        </template>
    </base-layout>
</div>
Vue.component('base-layout',{
        template:'<div class="container">\n' +
            '            <header>\n' +
            '                <slot name="header"></slot>\n' +
            '            </header>\n' +
            '            <main>\n' +
            '                 <slot name="main"></slot>\n' +
            '            </main>\n' +
            '                <footer>\n' +
            '                    <slot name="footer"></slot>\n' +
            '                </footer>\n' +
            '        </div>'
    })

clipboard.png

name用來定義額外的插槽,一個不帶 name 的 <slot> 出口會帶有隱含的名字「default」(即爲默認的插槽)。<template> 元素中的全部內容都將會被傳入相應的插槽。任何沒有被包裹在帶有 v-slot 的 <template> 中的內容都會被視爲默認插槽的內容。
與已經廢棄的slot特性不一樣,新版本使用v-slot: 來代替 slot=" "
注意 v-slot 只能添加在一個 <template> 上 (只有一種例外狀況),這一點和已經廢棄的 slot 特性不一樣。

後備內容

Vue.component('submit-button',{
       template:'<button type="submit">\n' +
           '            <slot>Submit</slot>\n' +
           '        </button>'
        })
<submit-button></submit-button>       //按鈕內文字爲Submit
<submit-button>POST</submit-button>   //按鈕內文字爲POST

做用域插槽

<div id="app2">
    <comp v-slot="user">
        {{user.username}}
    </comp>
</div>
 var CompA =Vue.component('comp', {
        template:'<div>' +
            '<slot :username="usernameA"></slot>' +
            '</div>',
        data(){
            return {
            usernameA:'Kayee'
        }
    }
    })

clipboard.png
子組件中的usernameA傳到父組件中,綁定在 <slot> 元素上的特性被稱爲插槽 prop

插槽的縮寫 v-slot:xxx 等價於#xxx

動態插槽名v-slot:[dynamicSlotName]

動態組件

<div id="app1">
        <div id="title">
            <button @click="changeTab('tab1')">Tab01</button>
            <button @click="changeTab('tab2')">Tab02</button>
        </div>
        <keep-alive>
                <component v-bind:is="currentTab"></component>
        </keep-alive>

    </div>
      Vue.component('tab1',{
        data:function () {
            return{
                count:0
            }
        },
        template:'<div class="tab">' +
            '{{count}}' +
            '<button @click="addCounter">+1</button>' +
            '</div>',
        methods: {
            addCounter(){
                this.count++
            }
        }
    })
    Vue.component('tab2',{
        data:function () {
            return{
                count:100
            }
        },
        template:'<div class="tab">' +
            '{{count}}' +
            '<button @click="subCounter">-1</button>' +
            '</div>',
        methods: {
            subCounter(){
                this.count--
            }
        }
    })
    new Vue({
        el:'#app1',
        data:{
            currentTab:'tab1'
        },
        methods:{
            changeTab(tabName){
                this.currentTab = tabName
            }
        }
    })

clipboard.png

clipboard.png
1.關於is特性來切換tab組件
2.keep-alive 來使數據獲得緩存記錄

異步組件

Vue.component('async-example',function (resolve,reject) {
        setTimeout(function () {
         // 向 `resolve` 回調傳遞組件定義
            resolve({
                template:'<div>I am async!</div>'
            })
        },1000)
    })

clipboard.png

clipboard.png

解析 DOM 模板時的注意事項

clipboard.png

相關文章
相關標籤/搜索