vue组件(父子组件传值、非props特性、作用域插槽、动态组件、v-once)

一、组件使用细节点

组件是可复用的 Vue 实例,且带有一个名字。
我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用

  • 定义全局组件,data里的data格式
Vue.component('row',{
    data:function(){
        return{
            content:'this is a row'
        }
    },
    template:'<tr><td>{{content}}</td></tr>'
})
  • tbody下只支持tr标签 直接使用row组件会有bug,需使用is属性
<table>
    <tbody>
        <tr is="row"></tr>
        <tr is="row"></tr>
        <tr is="row"></tr>
    </tbody>
</table>
  • 通过创建引用ref来操作DOM
<div ref='hello' @click="handleClick">
    hello world
</div> 

二、父子组件传值

  • 加了:之后为js表达式

  • 父组件通过属的形式给子组件传值 子组件通过事件触发的形式传值

  • 父组件监听change事件并执行handleChange

<div id="root">

        <counter :count="0" @change="handleChange"></counter>
        <counter :count="1" @change="handleChange"></counter>
        <div>{{totle}}</div>
    </div>
var counter={
    //子组件接收
    props:['count'],
    data:function(){
        return{
        /*子组件不能直接修改父组件传过来的值,可以先用number接收再修改*/
            number: this.count
        }
    },
    template:'<div @click="handleClick">{{number}}</div>',
    methods:{
        handleClick:function(){
            this.number++;
            /*子组件触发change事件*/
            this.$emit('change',1)
        }
    }
}

var vm = new Vue({
    el:"#root",
    data:{
        totle:1
    },
    components:{
        /*父组件接收*/
        counter:counter
    },
    methods:{
        handleChange:function(step){
            this.totle+=step
        }
    }
})

三、给组件绑定原生事件

  • click.native修饰符,即可绑定原生事件
<div id="root">
    <child @click.native="handleClick"></child>
</div>

四、组件参数校验与非props特性

  • props特性:父组件向子组件传值的时候传递了content,子组件在props里声明了content,content属性不会显示在dom标签里面
  • 非props特性:父组件向子组件传递了属性,子组件没有声明接收,子组件里不能使用,dom标签上会显示属性;
Vue.component('child',{
        //
        props:{
            //约束条件,传递的数据类型为String或者Number
            //content:[String,Number]
            content:{
                type:String,
                //必须要传参数
                //requierd:true
                //required:false,
                //如果没有传值,content值默认为default value
                //default:'default value',
                validator:function(value){
                    //value长度大于5
                        return (value.length>5)
                }
            }
        },
        template:'<div>{{content}}</div>'
    })

五、非父子组件传值

<div id="root">
    <child content="Dell"></child>
    <child content="Lee"></child>
</div>
  • Bus/总线/发布订阅模式/观察者模式
Vue.prototype.bus=new Vue()

Vue.component('child',{
    data:function(){
        return{
            selfContent:this.content
        }
    },
    props:{
        content:String
    },
    template:'<div @click="handleClick">{{selfContent}}</div>',
    methods:{
        handleClick:function(){
            this.bus.$emit('change',this.selfContent)
        }
    },
    mounted:function(){
        var this_=this
        this.bus.$on('change',function(msg){
            this_.selfContent= msg
        })
    }
})

六、vue中的插槽

<body-content >
<!-- 插槽 -->
<!-- 具名插槽 -->
    <div class='header' slot='header'>header</div>
    <div class='footer' slot='footer'>footer</div>
</body-content>

如果父组件中没有插槽内容,在子组件中使用可以定义默认内容

Vue.component('body-content',{
    template:'<div><slot>默认内容</slot><slot name="header"></slot><div class="content">content</div><slot name="footer"></slot></div>'
})

七、vue的作用域插槽

作用域插槽

<child>
    <template slot-scope="props">
        <h1>{{props.item}}</h1>
    </template>
</child>
Vue.component('child',{
        data:function(){
            return{
                list:[1,2,3,4]
            }
        },
        template:'<div><ul><slot v-for="item of list" :item=item></slot></ul></div>'
    })

八、动态组件与v-once指令

动态组件

<!-- <component :is="type"></component> -->
<child-one v-if="type==='child-one'"></child-one>
<child-two v-if="type==='child-two'"></child-two>
<button @click="handleBtnClick">change</button>

v-once提升性能,使用组件后不回销毁,存入内存,下次可以直接使用,不用再次创建

Vue.component('child-one',{
    template:'<div v-once>child-one</div>'
})

Vue.component('child-two',{
    template:'<div v-once>child-two</div>'
})

var vm = new Vue({
    el:'#root',
    data:{
        type:'child-one'
    },
    methods:{
        handleBtnClick:function(){
            this.type=(this.type==='child-one'?'child-two':'child-one');
        }
    }
})

猜你喜欢

转载自blog.csdn.net/weixin_43043994/article/details/82726737
今日推荐