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