深入理解vue组件

栏目: JavaScript · 发布时间: 4年前

内容简介:在在运用组件的时候,会出现想在这个标签内使用组件,但这个标签内并不支持的情况,如下我们看到

html 语法中, table 标签内就必须是 tr 标签, tr 标签下就必须是 td 标签, ul 标签下就必须是li标签 等等 标签间的嵌套规则

在运用组件的时候,会出现想在这个标签内使用组件,但这个标签内并不支持的情况,如下

<div id="app">
      <table>
        <tbody>
        	<tr>
            	<td>this  is a row</td>
            </tr>
            <tr>
            	<td>this  is a row</td>
            </tr>
            <tr>
            	<td>this  is a row</td>
            </tr>
        </tbody>
      </table>
    </div>

复制代码

我们看到 tr 标签这一部分重复了几次,我们可以试着用组件的方式,写出它,如下

<div id="app">
      <table>
        <tbody>
          <row></row>
          <row></row>
          <row></row>
        </tbody>
      </table>
    </div>

    <script>
      Vue.component("row", {
          template:"<tr><td>this is a row</td></tr>"
      });
      var app = new Vue({
        el: "#app"
      });
    </script>
复制代码

然后,我们打开浏览器测试下,

深入理解vue组件

虽然展示结果一样,但我们可以看待 tr 这部分标签出现在了 table 标签外部,这就是 table 标签不支持内部嵌套 不是 tr 标签的情况

这时候,我们就可以使用is了

<table>
    <tbody>
    	<tr is="row"></tr>//采用table内支持的标签,is后面接组件的名字
    </tbody>
</table>
复制代码

这里就不贴图了,这时,table标签的嵌套就正常了

组件中data的使用

在子组件中,data必须是一个函数,并且该函数要返回一个对象

这是因为子组件会重复使用,而他们之间需要有独立数据存储内存,这样数据才不会互相影响,如果在组件中data是一个对象,那么,所有组件的数据都指向同一块内存。

需要操作dom实例时,$refs出现了

如果你需要在父组件中,直接访问子组件的实例

可以通过 ref 给子组件加个id

ref="one"

然后父组件中,这样访问

this.$refs.one

现在我们用 ref 来做个小例子

深入理解vue组件

当我们点击上面的两个小数,会自增,最下的数字是两个小数是总回

子组件代码

Vue.component("count",{
        data:function(){
            return {
                number:0,
            }
        },
        template:"<div @click='add'>{{number}}</div>",
        methods:{
            add:function(){
                this.number++;
                this.$emit("change")//当被点击时,会触发父组件的change事件
            }
        }
    })
复制代码

html代码

<div id="app">
        <count ref="one" @change="allNum"></count>//用ref给子组件设置一个id,one
        <count ref="two" @change="allNum"></count>
        <div>{{all}}</div>
    </div>
复制代码

父组件代码

var app = new Vue({
        el:"#app",
        data:{
            all:0
        },
        methods:{
            allNum:function(){
                this.all=this.$refs.one.number+this.$refs.two.number;
                //在父组件中,可以通过this.$refs.ref来获取子组件的实例,
            }
        }
    })
复制代码

二、父子组件间的传值

父组件想要给子组件传值,必须在调用子组件的html上写上要传值的属性名和值,如下

<count :count="3"></count> 这里要注意 :属性名 后面接的都是一个js表达式,所以这里的3是一个数值类型

而在子组件中,要接受父组件的传值,则必须在 propps:[] 中加一个同样的属性名, props:["count"]

重点,在这里要注意vue的单向数据流概念,就是父组件可以给子组件传值, 但子组件不能随意直接修改父组件传过来的值,必须先将父组件传过来的值复制一份,放在子组件的data中后,然后对data中的值进行修改

如下

Vue.component("count",{
    props:['count'],
    data:function(){
        return {
            number:this.count
        }
    }
})
复制代码

如上,只能对父组件传过来的值的 副本 进行操作,这是因为,传进的是 基础数据类型 还好,如果父组件传递的是一个 引用型 的数据,那么子组件直接改动这个数据,就有可能对其他引用该数据的组件造成干扰

子组件给父组件传值,要借助$emit去触发父组件自定义的事件,

this.$emit("change",1) ;change是父组件自定义的事件,而1,就是我们要传递的值了,

现在我们来利用父子组件的传值,做一个简单的计数器

<div id="app">
        <count :count="one" @change="allNum"></count>
    //@change是父组件自定义的事件,触发了change//就会去执行allNum函数
        <count :count="two" @change="allNum"></count>
    //:count 是要传递的属性名,two是要传递的值,在data中,two对应0;
        {{all}}
    </div>
    <script>
    var count = {
        props:['count'],//用count来接受父组件传递过来的值
        data:function(){
            return {
                number:this.count,//记得单项数据流,要将父组件的传值,复制一份,放在子组件data中
            }
        },
        template:'<div @click="add">{{number}}</div>',
        methods:{
            add:function(){
                this.number++;
                this.$emit("change",1);//触发change事件,传值是1;
            }
        }
    }
    var app = new Vue({
        el:"#app",
        data:{
            all:0,
            one:0,
            two:0
        },
        components:{
            count:count,
        },
        methods:{
            allNum:function(value){//value来接受$emit的传值
                this.all+=value;
            }
        }
    })
复制代码

效果如下:

深入理解vue组件

三、组件参数校验与非Props特性

组件参数校验

当父组件给子组件传值时,我们希望对该值进行约束,如下

props:{
    content:{
        type:String,//限制传过来的值必须是字符串,
        required:false,//是否必须传递该值
        default:'default value',//默认值
        validator:function(value){//
            return (value.length>5);//该值的长度必须大于5
        }
    }
}
复制代码

props特性

父组件给子组件传值时,切好子组件的props中有对应的prop进行接收,那么这就是props特性,,父组件给子组件传递的值,不会显示在html中,

向相反,非props特性,则会显示在html中

四、给组件绑定原生事件

父组件在子组件上绑定了一个事件,想要触发该事件,只能通过 触发自定义事件的方式 去触发,或者在加上事件修饰符.native

先看第一种,不加修饰符,不触发自定义事件

<div id="app">
        <child @click="onClick"></child>
    </div>
    <script>
    Vue.component('child',{
        template:'<div>child</div>',
    })
    var app = new Vue({
        el:"#app",
        methods:{
            onClick:function(){
                alert('click');
            }
        }
    })
    </script>
复制代码

在浏览器中,我们发现,点击child并没有任何效果,

深入理解vue组件

这就是想要触发父组件在子组件上绑定的事件,只能通过触发自定义事件的方式去触发,现在改代码如下:

<div id="app">
        <child @click="onClick"></child>
    </div>
    <script>
    Vue.component('child',{
        template:'<div @click="childClick">child</div>',
        methods:{
            childClick:function(){
                this.$emit("click");//触发父组件的自定义事件,click
            }
        }
    })
    var app = new Vue({
        el:"#app",
        methods:{
            onClick:function(){
                alert('click');
            }
        }
    })
    </script>
复制代码
深入理解vue组件

或者给加上一个事件修饰符.native也可以达到相同的效果

<child @click.native="onClikc"></child>
复制代码

五、非父子组件间的传值

这里先介绍一种总线的模式。

<div id="app">
        <child content="胡"></child>
        <child content="志武"></child>
    </div>
    <script>
        Vue.prototype.bus = new Vue();
        Vue.component("child",{
            props:['content'],
            data:function(){
                return {
                    name:this.content,
                }
            },
            template:'<div @click="exchange">{{name}}</div>',
            methods:{
                exchange:function(){
                    this.bus.$emit("change",this.name)
                }
            },
            //组件被挂载时,
            mounted:function(){
                var that = this;
                this.bus.$on("change",function(msg){
                    that.name=msg;
                })
            }
        })
        var app = new Vue({
            el:"#app",
        })
    </script>
复制代码

我们在 Vueprototype 上挂载了一个 bus ,这个bus是一个 vue 的实例,子组件要互相传值时,就可以用这个共同的祖先bus来监听和触发相应的事件,并借助这个共同的祖先来传值

深入理解vue组件

六、使用插槽

slot可以让我们在组件的某个位置插入想要的内容

Vue.component("child",{
            template:`<div>
                        <slot name="header">默认内容</slot>
                        <div>content</div>
                        <slot name="footer">默认内容</slot>
                      </div>`
        })V
复制代码
<div id="app">
        <child>
            <div slot="header">我是头部</div>
            <div slot="footer">我是尾部</div>
        </child>
    </div>
复制代码

如果在插槽位置没有插入内容,则会显示默认内容

作用域插槽

当子组件在做遍历,而希望这个遍历的dom结构由外部决定时,可以使用作用域插槽

<div id="app">
        <child >
            <template slot-scope="props">//template是必须写的
                <h1>{{props.item}}</h1>//props可以任意写,而item必须和template中的`:item`一致
            </template>
        </child>
    </div>
    <script>
        Vue.component("child",{
            data:function(){
                return {
                    list:[1,2,3,4,5]
                }
            },
            template:`
                    <ul>
                        <slot v-for="item of list"
                            :item=item>//这里的:item是要传值给html实际插槽部分的
                        </slot>
                    </ul>
            `
        })
        new Vue({
            el:"#app",
        })
    </script>
复制代码

动态组件和v-once

<component> 是vue自带标签,

<component :is="组件名"> component会根据is后面组件名的不同而动态加载不同的组件

v-once可以把组件放在内存中,可以有效提高性能

template:`<div v-once>child ONE</div>`
复制代码

以上所述就是小编给大家介绍的《深入理解vue组件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

特斯拉之父

特斯拉之父

竹内一正 / 千太阳 / 中信出版社 / 2014-12 / 39.00

马斯克的成就前无古人地跨越了各个领域,曾大起大落,成为亿万富翁后,又曾濒临破产。他凭借极强的控制欲、坚强的意志力把人生浓缩得异常精彩,拓展了人类对自身智力与能力限度的想象。乔布斯离开了,马斯克来了,后者离人更远,离神更近。 他的创业故事就是一部真实的好莱坞大片 美国《财富》杂志 “2013年度商业人物” 史上最富激情、传奇、未来感的企业家 他是个外表优雅的生意人、太空的挑战......一起来看看 《特斯拉之父》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具