深入理解vue组件

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

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

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组件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

MultiCharts Powerlanguage 语法字典

MultiCharts Powerlanguage 语法字典

MultiCharts中国技术顾问团队 / 东方出版社 / 2013-9-1 / 38

MC编程工具书,适用于MC7.4及8.5版本一起来看看 《MultiCharts Powerlanguage 语法字典》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码