Vue前端框架的學習——04—(給自定義組件添加屬性、單一根元素、子組件事件和傳遞事件到父組件、自定義組件v-model、插槽、生命週期函數)

1、給組件添加屬性

像原始的html元素都有自己的一些屬性,而我們自己創建的組件,也可以通過prop來添加自己的屬性。這樣別人在使用你創建的組件的時候就可以傳遞不同的參數了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
         <button_list v-bind:books="books"> </button_list>

    </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    //組件
    Vue.component('button_list',{

        //給組件添加屬性   propertys   關鍵字
        props:['books'],
        template:`
        <table>
             <tr>
                 <th>序號</th>
                 <th>標題</th>
             </tr>
             <tr v-for="(book,index) in books">
                 <td>{{index+1}}</td>
                 <td>{{book.title}}</td>
             </tr>
        </table>
        `,  //button_list中封裝的內容模板就是這句
        data:function(){               //這裏的data寫法不同於new vue中的data
            return {                 //這裏需要{}
                count:0
                }
        }
    })
    new Vue({
        el:"#app",
        data:{
            books:[
                {'title':"python","id":1},
                {'title':"java","id":2},
                {'title':"php","id":3},
            ]

        }
    })

</script>

2、單一根元素

如果自定義的組件中,會出現很多html元素,那麼根元素必須只能有一個,其餘的元素必須包含在這個根元素中。比如以下是一個組件中的代碼,會報錯:
在這裏插入圖片描述

3、子組件事件和傳遞事件到父組件

子組件中添加事件跟之前的方式是一樣的,然後如果發生某個事件後想要通知父組件,那麼可以使用this.$emit函數來實現。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <button_list v-for="book in books" v-bind:book="book" @check_change="checks"></button_list>
        <div v-for="cbook in component_book">
            {{cbook.title}}
        </div>
   </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    //組件
    Vue.component('button_list',{
        //給組件添加屬性   propertys   關鍵字
        props:['book'],
        template:`
        <div>
            <span>{{book.title}}</span>
            <input type="checkbox" @click="Oncheck">
        </div>
        `,  //button_list中封裝的內容模板就是這句
        methods:{
            Oncheck:function(){
                this.$emit('check_change', this.book)
            }
        }
    })
    new Vue({
        el:"#app",
        data:{
            books:[
                {'title':"python","id":1},
                {'title':"java","id":2},
                {'title':"php","id":3},
            ],
            component_book:[],
        },
        methods:{
            checks:function(book){
                console.log(book)
                var index=this.component_book.indexOf(book)    //indexOf   返回的是book的下標
                if(index >= 0){
                    this.component_book.splice(index,1)     //刪除一個下標爲index的元素
                }else{
                    this.component_book.push(book)
                }
                
            }
        }
    })
</script>

在這裏插入圖片描述

4、自定義組件v-model

一個組件上的v-model默認會利用名爲value的prop(屬性)和名爲input的事件,但是像單選框、複選框等類型的輸入控件可能會將value特性用於不同的目的。這時候我們可以在定義組件的時候,通過設置model選項可以用來實現不同的處理方式。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <stepper v-model:value="goods_count"></stepper> 
   </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    //計步器
    Vue.component('stepper',{
        //給組件添加屬性   propertys   關鍵字
        props:['count'],

        model:{                //代表什麼情況下觸發這個v-model的行爲
            event:'count_change',
            prop:'count'
        },
        template:`
        <div>
            <button @click="sub">-</button>
            <span>{{count}}</span>
            <button @click="add">+</button>
            
        </div>
        `,  //button_list中封裝的內容模板就是這句
        methods:{
            sub:function(){
                this.$emit('count_change', this.count-1)
            },
            add:function(){
                this.$emit('count_change', this.count+1)
            }

        }
    })
    new Vue({
        el:"#app",
        data:{
            goods_count:0,
        },
    })
</script>

在這裏插入圖片描述
其中的props定義的屬性分別是給外面調用組件的時候使用的。model中定義的prop:'count’是告訴後面使用v-model的時候,要修改哪個屬性;event:'count-chang’是告訴v-model,後面觸發哪個事件的時候要修改屬性。

5、插槽

我們定義完一個組件後,可能在使用的時候還需要往這個組件中插入新的元素或者文本。這時候就可以使用插槽來實現。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <new_link v-bind:url="url">         
            個人中心
        </new_link>
   </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    //計步器
    Vue.component('new_link',{
        //給組件添加屬性   propertys   關鍵字
        props:['url'],

        template:`
        <a v-bind:href="url">
            <slot></slot>
        </a>
        `,  
    })
    new Vue({
        el:"#app",
        data:{
            url:"https://www.baidu.com",
        },
    })
</script>

當組件渲染的時候,將會被替換爲“個人中心”。插槽內可以包含任何模板代碼,包括HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <new_link v-bind:url="url">
            個人中心
            {{name}}
            <template v-slot:header>這是header</template>
            <template v-slot:main>這是main</template>          
            <div></div>
        </new_link>
   </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    //計步器
    Vue.component('new_link',{
        //給組件添加屬性   propertys   關鍵字
        props:['url'],

        template:`
        <a v-bind:href="url">
            <div>
                <slot></slot>
            </div>

            <div>
                <slot name="main"></slot>
            </div>
            
            <div>
                <slot name="header"></slot>
            </div>
        </a>
        `,  
        data:function(){
            return {
                name:"zzz",
            }
        }
    })
    new Vue({
        el:"#app",
        data:{
            url:"https://www.baidu.com",
        },
    })
</script>

如果沒有包含一個元素,則該組件起始標籤和結束標籤之間的任何內容都會被拋棄。

6、生命週期函數

生命週期函數代表的是Vue實例,或者是Vue組件,在網頁中各個生命階段所執行的函數。生命週期函數可以分爲創建階段和運行期間以及銷燬期間。

  • 其中創建期間的函數有beforeCreate、created、beforeMount、mounted;
  • 運行期間的函數有beforeUpdate、updated;
  • 銷燬期間有beforeDestroy、destroyed。

以下是官方文檔給到的一張圖,從這種圖中我們可以瞭解到每個部分執行的函數。
在這裏插入圖片描述
創建期間:

beforeCreate:
Vue或者組件剛剛實例化,data、methods都還沒有被創建。

created:
此時data和methods已經被創建,可以使用了。模板還沒有被編譯。

beforeMount:
created的下一階段。此時模板已經被編譯了,但是並沒有被掛在到網頁中。

mounted:
模板代碼已經被加載到網頁中了。此時創建期間所有事情都已經準備好了,網頁開始運行了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <p id="username">{{username}}</p>
   </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    Vue.component('content',{
        template:`
            <div>
                <slot name="header" :navs="navs"></slot>
            </div>
            <div>
                <slot name="footer" :navs="navs"></slot>
            </div>
        `,  
        data:function(){
            return {
                navs:["1","2","3"]
            }
        }
    }),

    new Vue({
        el:"#app",
        data:{
            username:"yyy"
        },
        methods:{
            demo:function(){
                return "hello"
            }
        },
        //beforeCreate:Vue或者組件剛剛實例化,data、methods都還沒有被創建
        beforeCreate(){
            // console.log(this.username);
            // console.log(this.demo);
            // console.log(123);
            // console.log("----------------------");
        },
        //此時data和methods已經被創建,可以使用了。模板還沒有被編譯。
        created(){
            // console.log(this.username);
            // console.log(this.demo);
            // console.log(123);
            // console.log("----------------------");
        },
        // created的下一階段。此時模板已經被編譯了,但是並沒有被掛在到網頁中。
        beforeMount(){
            //console.log(document.getElementById('username').innerText)
        },
        mounted(){
            console.log(document.getElementById('username').innerText)   //獲取文本信息
        }
    })
</script>

運行期間:

beforeUpdate:
在網頁網頁運行期間,data中的數據可能會進行更新。在這個階段,數據只是在data中更新了,但是並沒有在模板中進行更新,因此網頁中顯示的還是之前的。

updated:
數據在data中更新了,也在網頁中更新了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <p id="username">{{username}}</p>
        <!-- v-model雙向綁定,修改username的值 -->
        <input type="text" v-model="username">
   </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    Vue.component('content',{
        template:`
        `,  
        data:function(){
            return {
                
            }
        }
    }),

    new Vue({
        el:"#app",
        data:{
            username:"yyy"
        },
        methods:{
            demo:function(){
                return "hello world"
            }
        },
        mounted(){
            // console.log(document.getElementById('username').innerText)   //獲取文本信息
        },
        // 數據在data中更新了,也在網頁中更新了
        update(){
            console.log(document.getElementById('username').innerText)   

        }
    })
</script>

銷燬期間:

beforeDestroy:
Vue實例或者是組件在被銷燬之前執行的函數。在這一個函數中Vue或者組件中所有的屬性都是可以使用的。

destroyed:
Vue實例或者是組件被銷燬後執行的。此時Vue實例上所有東西都會解綁,所有事件都會被移除,所有子元素都會被銷燬。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <p id="username">{{username}}</p>
        <!-- v-model雙向綁定,修改username的值 -->
        <input type="text" v-model="username">

        <error-view v-bind:message="message" v-if="message"></error-view>
        <button @click="message=' ' ">點擊</button>
   </div>
</body>
</html>

<!--vue引入   必須聯網-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<script>
    Vue.component('error-view',{
        props:['message'],
        template:`
            <p style="color:red">{{message}}</p>
        `, 
        methods:{
            
        },
        data:function(){
            return {
                
            }
        },
        beforeDestroy(){
            console.log('hello')
        },


    }),

    new Vue({
        el:"#app",
        data:{
            username:"yyyyyyyyyy",
            message:"錯誤信息",
        },
        methods:{
            demo:function(){
                return "hello world"
            }
        },
        mounted(){
            // console.log(document.getElementById('username').innerText)   //獲取文本信息
        },
        // 數據在data中更新了,也在網頁中更新了
        update(){
            console.log(document.getElementById('username').innerText)   
        }
    })
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章