把实例的基础属性过了一遍,现在来看事件以及之前很少接触的动画过渡效果。

组件

组件的本质是什么,从JS代码和Vue的角度来说,就是一个规定好属性和值写法的对象,和新创建Vue实例传入的对象没有本质上的区别。

当然与直接生成Vue实例相比,组件还是有属于自己的特点,那就是不同的属性及其作用。就单个组件来说,最大的变化是template属性,也就是组件要渲染的HTML部分。

此外data变成了一个函数,返回了一个对象,这是因为组件需要复用,如果指定为具体值,则各个组件都会共享基础数据,就比较可怕了。

还有一个重要的就是props,表示父组件传入的数据。

props

props的属性有类型,是否required,默认值,这个都已经知道了。新了解的是还可以有一个叫做validator名称的方法,用于验证这个属性是否OK。返回true就说明OK。:

<div id="app">
    <list :price="3"></list>
    <list :price="-33"></list>
</div>

<script>
    Vue.component('list', {
        template: '<div>Price is {{price}}</div>',
        props: {
            price:{
                type:Number,
                default:0,
                validator(val){
                    return val >= 0;
                }
            }
        }
    });
    new Vue({
        el: '#app'
    });
</script>

这个运行起来,Vue会提示:

vue.js:634 [Vue warn]: Invalid prop: custom validator check failed for prop "price".

found in

---> <List>
       <Root>

注意这个方法只能是这个名称,不能修改名称。

slot

之前已经知道普通插槽,具名插槽和作用域插槽。现在slot和作用域插槽都要废弃,引入了v-slot指令,只能作用于<template>元素。

2.6之后的Vue的组件大改了,用一个例子看明白:

<div id="app">
    <myslots>
        <template v-slot:default>父组件插入默认插槽</template>
        <template v-slot:saner>父组件插入具名插槽</template>
        <template v-slot:scope="cony">{{cony.innerobject.name}}</template>
    </myslots>
    </div>

<script>
    Vue.component('myslots', {
        template: '<div><p><slot>不具名插槽默认内容</slot></p>' +
            '<p><slot name="saner">具名插槽默认内容</slot></p>' +
            '<p></p><slot name="scope" :innerobject="person">绑定子组件属性的插槽</slot></div>',
        data: function () {
            return {
                person: {
                    name: 'jenny'
                }
            }
        }
    });
    new Vue({
        el: '#app'
    });
</script>

主要就是v-slot指令要搭配template来使用,作用域的使用方法很简单,父的绑定名称.子的属性名.实际属性即可。

自定义事件

自定义事件$emit已经知道了,现在要了解一下可以用其他方式在父组件上添加和取消事件监听器:

<div id="app">
        <events ref="tar"></events>
        <button @click="cancel">取消事件绑定</button>
</div>

<script>
    Vue.component('events', {
        template: '<div><button @click="event1">反复触发事件</button><button @click="event2">一次事件</button></div>',
        methods:{
            event1:function () {
                this.$emit('repeat')
            },
            event2:function () {
                this.$emit('once')
            }
        }
    });
    new Vue({
        el: '#app',
        methods: {
            handle1:function () {
                console.log("反复事件触发了")
            },
            handle2:function () {
                console.log('一次事件触发了')
            },
            cancel:function () {
                this.$refs.tar.$off('repeat',this.handle1)
                this.$refs.tar.$off('once',this.handle2)
            }
        },
        mounted: function () {
            this.$refs.tar.$on('repeat',this.handle1)
            this.$refs.tar.$once('once',this.handle2)
        }
    });
</script>

如果先按了下边的取消事件绑定按钮,再点击按钮,就没有处理事件的函数了。

子组件上没有进行绑定props的属性

如果在子组件上设置了没有绑定props的普通HTML属性,这些属性会被放到子组件的外层元素上去。如果父组件设置的属性和子组件模板内的属性相同,父组件的设置会覆盖子组件。看例子:

<div id="app">
    <custom-button type="submit">Click me!</custom-button>
</div>

<script>
    const CustomButton = {
        template: '<button type="button"><slot></slot></button>'
    };
    new Vue({
        el: '#app',
        components: {
            CustomButton
        }
    });
</script>

这时候实际渲染出来的按钮的属性是submit。大部分属性会覆盖,但是classstyle属性则会叠加,所以有时候可以方便的通过父组件去控制样式。

看完了Vue js快跑,我发现倒是之前Vue实例的一些使用有很多知识点没搞要求,因为Vue实例看的是国人的书。关于Vuex和Router,是跟着老外的视频看的,却发现都学的比较全。

不得不感叹看书还真得官方文档+老外的书一起看,看国人写的书还是要慎重啊。