Vue实战项目开发--深入理解vue组件

项目的源代码在GitHub上点击查看


组件使用的细节点

  • 使用is属性解决模板标签上出现bug的情况
  • 在子组件定义data时,data必须是一个函数,而不能是一个对象(因为子组件会多次调用,每个子组件享用自己的数据,而不是像根组件享有一套数据,通过函数来返回数据,就是让每个子组件拥有独立的数据
  • ref:可以在子组件上定义不同的ref,然后就可以通过引用来取得子组件的数据

    注意:另外的两个案例的代码在GitHub上

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件使用中的细节点</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <table>
            <tbody>
                //通过is属性,让子组件显示出来,也满足h5的编码规范
                <tr is="row"></tr>
                <tr is="row"></tr>
                <tr is="row"></tr>
            </tbody>
        </table>
    </div>

    <script>

        Vue.component("row",{
            template: '<tr><td>this is row</td></tr>'
        })

        var vm =new Vue({
            el: "#root"
        })
    </script>
</body>
</html>

父子组件的数据传递

  • 父组件向子组件传值都是通过属性来传递的,子组件通过props来接受(单向数据流:子组件只能用父组件传递过来的参数,不能修改父组件传递过来的内容
  • 子组件向父组件传值是通过事件的形式,把触发的事件向父组件传递

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父子组件的数据传递</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <counter :count="2" @inc="handleIncrease"></counter>
        <counter :count="3" @inc="handleIncrease"></counter>
        <div>{{total}}</div>
    </div>

    <script>


        var counter = {
            props: ['count'],
            data: function () {
                return {
                    number:  this.count
                }
            },
            template: '<div @click="handleClick">{{number}}</div>',
            methods: {
                handleClick: function () {
                    this.number =  this.number + 2
                    this.$emit('inc', 2)
                }
            }
        }
        var vm = new Vue({
            el: "#root",
            data: {
                total: 5
            },
            components: {
                counter: counter
            },
            methods: {
                handleIncrease: function (step) {
                   this.total += step
                }
            }
        })
    </script>
</body>
</html>

组件参数校验与非props特性

required:确定父组件是否必须先向子组件传值

default:默认值,如果父组件没有向子组件传值,就显示默认值

validator:自定义校验器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件参数校验与非props特性</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <child content="hell"></child>
    </div>

    <script>

        Vue.component('child',{
            props: {
                content: {
                    type: String,
                    //required: false,
                    //default: 'default value'
                    validator: function (value) {
                        return (value.length > 5)
                    }
                }
            },
            template: '<div>{{content}}</div>'
        })
        var vm =new Vue({
            el: "#root"
        })
    </script>
</body>
</html>

非props特性:

  • 子组件没有定义props来接受父组件传递来的参数,就引起非props特性
  • 申明了一个非props特性,这个属性会展示在子组件的dom标签上

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件参数校验与非props特性</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <child content="hell"></child>
    </div>

    <script>

        Vue.component('child',{
//            props: {
//                content: {
//                    type: String,
//                    //required: false,
//                    //default: 'default value'
//                    validator: function (value) {
//                        return (value.length > 5)
//                    }
//                }
//            },
            template: '<div>hello world</div>'
        })
        var vm =new Vue({
            el: "#root"
        })
    </script>
</body>
</html>

非父子组件间的传值

  • 可以通过vue的vuex框架实现非父子组件间的传值
  • 总线机制:发布-订阅模式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>非父子组件间传值(Bus/总线/发布订阅模式/观察者模式)</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <child content="Dell"></child>
        <child content="Lee"></child>
    </div>

    <script>
        //向vue实例的类添加一个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
                })
            }
        })

        var vm =new Vue({
            el: "#root"
        })
    </script>
</body>
</html>

注意:子组件不能直接改变父组件穿的值,不然会报错,因为要满足单向数据流

在Vue中使用插槽

  • 通过插槽,可更方便地向子组件传递dom元素,同时子组件使用这个插槽也很简单
  • 通过使用具名插槽,可以插入你想插入地内容
  • 作用域插槽:父组件调用子组件的时候,给子组件传了一个插槽(作用域插槽,这个插槽必须是template结尾的,还需要申明父组件接受子组件的数据放在那里的,还给子组件的模板的信息),当子组件做循环或者某一部分时,它的DOM结构由外部传递时
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue中的插槽(slot)</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <child>
            <p>Dell</p>
        </child>
    </div>

    <script>

        Vue.component('child',{
            template:  `<div>
                            <p>Hello</p>
                            <slot></slot>
                        </div> `
        })

        var vm = new Vue({
            el: "#root"
        })

    </script>
</body>
</html>

作用域插槽:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue中的作用域插槽(slot)</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <child>
            <template slot-scope="props">
                <h1>{{props.item}}</h1>
            </template>
        </child>
    </div>

    <script>

        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>`
        })
        var vm = new Vue({
            el: "#root"
        })

    </script>
</body>
</html>

动态组件和v-once指令

  • 通过componet可以实现动态组件效果,
  • v-once:可以提高静态资源的展示效率,并且把组件放在内存中
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动态组件与v-once指令</title>
    <script src="./vue.js"></script>
</head>
<body>

    <div id="root">
        <!--动态组件-->
        <!--<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>
    </div>

    <script>

        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');
                }
            }
        })
    </script>
</body>
</html>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值