zoukankan      html  css  js  c++  java
  • Vue组件基础

    gitHub地址:https://github.com/huangpna/vue_learn/example里面的lesson06

    一 vue组件基本实例

     举个例子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>app1</title>
    </head>
    <body>
        <div id="app1">
            <button-counter></button-counter>    <!--注意:点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。-->
            <button-counter></button-counter>
            <button-counter></button-counter>
        </div>
    </body>
    <script src="../js/vue.min.js"></script>
    <script>
        Vue.component('button-counter',{   //全局注册一个组件
            data:function () {
                return {
                    count:0
                }
            },
            template:'<div><button @click="count++">点击一下</button>&nbsp;&nbsp;&nbsp;&nbsp;<span>{{count}}</span></div>'
        });
        new Vue({el:'#app1'}); //创建一个vue实例
    </script>
    </html>

    (1)因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

    (2)一个组建的data选项必须是一个函数,而不是像之前一样直接接受一个对象

    (3)有两种注册注册组件的方式:全局注册和局部注册;至此,我们的注册都只是通过Vue.component全局注册的。

    (4)全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

    二 通过prop给子组件传递数据

    举个例子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>app1</title>
    </head>
    <body>
        <div id="app1">
            <button-counter title="My journey with Vue"></button-counter>          //通过自定义特性传递值
            <button-counter title="Blogging with Vue"></button-counter>
            <button-counter title="Why Vue is so fun"></button-counter>
        </div>
    </body>
    <script src="../js/vue.min.js"></script>
    <script>
        Vue.component('button-counter',{   //全局注册一个组件
            props:['title'],    //可以传递任何类型的值
            data:function () {
                return {
                    count:0
                }
            },
            template:'<div><button @click="count++">点击一下</button>&nbsp;&nbsp;&nbsp;&nbsp;<span v-if="count == 1">{{title}}</span></div>'  //值显示,查看是否传递成功
        });
        new Vue({el:'#app1'}); //创建一个vue实例
    </script>
    </html>

    一个组件默认可以用过任意数量的prop,任何值都可以传递给任何 prop。在上述例子中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。

    一个 prop 被注册之后,你就可以像上面例子一样把数据作为一个自定义特性传递进来。

    例子2:

    注意:这个时候我们想要给每篇博文渲染一个组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>app2</title>
        <style>
            #app2>div{
                width:800px;
                height:160px;
                background-color: #ff4225;
                font-size:35px;
                text-align:center;
                line-height:160px;
                margin:0 auto  20px;
            }
        </style>
    </head>
    <body>
        <div id="app2">
            <my-content v-for="item in dataList" v-bind:num="item.id" v-bind:title="item.title"></my-content>  <!--动态传递值-->
        </div>
    </body>
    <script src="../js/vue.min.js"></script>
    <script>
        Vue.component('my-content',{
            props:['title','num'],
            data:function () {
    
            },
            template:'<div>{{title}}------{{num}}</div>'
        });
        new Vue({
            el:'#app2',
            data:{
                dataList: [
                    { id: 1, title: '博文组件' },
                    { id: 2, title: '博文组件' },
                    { id: 3, title: '博文组件' }
                ]
            }
        });
    </script>
    </html>

    但是很多时候我们的博文不止需要标题和内容,可能要传递的数据更多,这个时候组件就会变得越来越复杂,这个时候你可以变成只接受一个单独的dataList props。

    注意:必须将组件模板包含在一个父元素内,否则会报错。

    三 通过事件向父级组件发送消息

    举个例子(假如说我们现在需要引入一个可访问性的功能来放大博文的字号):

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>app2</title>
        <style>
            #app2>div>div{
                width:800px;
                height:160px;
                background-color: #ff4225;
                text-align:center;
                line-height:160px;
                margin:0 auto  20px;
            }
        </style>
    </head>
    <body>
    <div id="app2">
        <div :style="{fontSize:postFontSize + 'px'}">   <!--它可以在模板中用来控制所有博文的字号-->
            <my-content v-for="item in dataList" v-on:enlarge-text="changeFontSize" v-bind:num="item.id" v-bind:title="item.title"></my-content>
        </div>                                     <!--注意:然后我们用v-on 在博文组件上监听这个事件-->
    </div>
    </body>
    <script src="../js/vue.min.js"></script>
    <script>
        Vue.component('my-content',{
            props:['title','num'],
            data:function () {
    
            },                                                                                  //但是有的时候我们需要抛出一个特定的值,可以通过$emit的第二个参数
            template:`<div>{{title}}------{{num}}------<button v-on:click="$emit('enlarge-text',0.5)">点击放大字体</button></div>`  //现在我们需要给每篇博文添加一个按钮来放大字号
        });           //注意:这个时候如果说我们需要点击这个按钮,需要调用内容的$emit方法并列入事件的名称来向父级组件触发一个事件
        new Vue({
            el:'#app2',
            data:{
                dataList: [
                    { id: 1, title: '博文组件' },
                    { id: 2, title: '博文组件' },
                    { id: 3, title: '博文组件' }
                ],
                postFontSize: 20     //添加一个postFontSize数据属性来支持这个功能
            },
            methods:{
                changeFontSize:function ($event) {  //那么这个值将作为一个参数传入这个方法
                    let _this = this;
                    _this.postFontSize += $event;
                }
            }
        });
    </script>
    </html>

    注释:首先我们可以通过在父组件中添加一个postFontSize数据属性来支持这个功能,它可以在模板中用来控制所有博文的字号;然后我们需要给每篇博文添加一个按钮来放大字号,当点击这个按钮时,需要调用内容的$emit方法并列入事件的名称来向父级组件触发一个事件,然后我们需要用v-on 在博文组件上监听这个事件,但是有的时候我们需要抛出一个特定的值,可以通过$emit的第二个参数;如果这个事件处理函数是一个方法,那么这个值将作为一个参数传入这个方法。

    四 在组件上使用v-model

    举个例子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>app3</title>
    </head>
    <body>
        <div id="app3">
            <div>
                <span>输入框1: </span>
                <input v-model="searchText">
            </div>
            <!--等价于-->
            <custom-input v-bind:value="searchText" v-on:input="getInputV"></custom-input>
        </div>
    </body>
    <script src="../js/vue.min.js"></script>
    <script>
        Vue.component('custom-input',{
            props:['value'],
            template:`<div><span>输入框2: </span><input v-bind:value="value" v-on:input="$emit('input',$event.target.value)"></div>`
        });
        new Vue({
            el:'#app3',
            data:{
                searchText:''
            },
            methods:{
                getInputV:function (v) {
                    let _this = this;
                    _this.searchText = v;
                }
            }
        })
    </script>
    </html>

    五 通过插槽分发内容

    举个例子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>index4</title>
        <style>
            ._style{
                width:500px;
                height:220px;
                background-color: #ff4225;
            }
        </style>
    </head>
    <body>
        <div id="app4">
            <alert-box>
                Something bad happened.
            </alert-box>
        </div>
    </body>
    <script src="../js/vue.min.js"></script>
    <script>
        Vue.component('alert-box',{
            props:[],
            template:`<div class="_style"><span>Error!</span><slot></slot></div>`
        });
        new Vue({
            el:'#app4'
        })
    </script>
    </html>

    如你所见,我们只要在需要的地方加入插槽就行了——就这么简单!

    六 动态组件

    有时候在不同组件之间进行动态切换是非常有用的,举例说明:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>index5</title>
        <style>
            .tab-button:hover{
                background: red;
            }
            #app5>.active{
                background: red;
            }
        </style>
    </head>
    <body>
        <div id="app5">
            <button v-for="item in navs" v-bind:key="item"  v-bind:class="['tab-button',{active:item === currentTab}]" v-on:click="tab(item)">
                {{item}}
            </button>
            <!-- 组件会在 `currentTabComponent` 改变时改变 -->
            <component v-bind:is="currentTabComponent"></component>
        </div>
    </body>
    <script src="../js/vue.min.js"></script>
    <script>
        Vue.component('my-home',{
            template:'<div>Archive component111111</div>'
        });
        Vue.component('my-posts',{
            template:'<div>Archive component222222</div>'
        });
        Vue.component('my-archive',{
            template:'<div>Archive component333333</div>'
        });
        new Vue({
            el:'#app5',
            data:{
                currentTab:'Home',
                navs:['Home','Posts','Archive']
            },
            methods:{
                tab:function (v) {
                    let _this = this;
                    _this.currentTab = v;
                }
            },
            computed:{
                currentTabComponent:function () {
                    let _this = this;
                    return 'my-'+ _this.currentTab.toLowerCase();
                },
            }
        })
    </script>
    </html>

    在上述示例中,currentTabComponent 可以包括

    • 已注册组件的名字,或
    • 一个组件的选项对象

    七 解析DOM模板时的注意事项

    有些 HTML 元素,诸如 <ul><ol><table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li><tr> 和 <option>,只能出现在其它某些特定的元素内部。

    这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:

    <table>
    <blog-post-row></blog-post-row>
    </table>

    这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is 特性给了我们一个变通的办法:

    <table>
    <tr is="blog-post-row"></tr>
    </table>

    需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:

    到这里,你需要了解的组件的基础用法就了解完了,接下来需要深入学习组件了。

  • 相关阅读:
    arr.forEach()与for...in的用法举例
    git
    hql查询
    JAVA Hibernate工作原理及为什么要用
    mysql中key 、primary key 、unique key 与index区别
    aop
    hibernate json数据死循环
    nginx 转帖
    Maven搭建web项目
    ajaxfileupload 附加参数
  • 原文地址:https://www.cnblogs.com/1156063074hp/p/10063228.html
Copyright © 2011-2022 走看看