Vue-动态组件-单向数据流-跨组件通信-Prop验证

为什么组件中的data必须是一个函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    // const myComponent = function() {}
    // // 这个data在这里是一个对象
    // myComponent.prototype.data = {
    //     a: 1,
    //     b: 2
    // }
    // const component1 = new myComponent()
    // const component2 = new myComponent()
    //
    // component1.data.a = 5
    //
    // console.log(component2.data.a)
    /*
    * 如果是对象,不用function,返回每个组件的data都是内存中的同一个地址,一个数据改变了,其他的也会发生变化。
    *
    * 在JavaScript只有函数可以构成作用域,这就是data为什么是一个函数的原因,每个组件实例,都有自己的作用域,互相独立不会互相影响
    *
    * */
​
    const myComponent = function() {
        this.data = this.data()
    }
    myComponent.prototype.data = function() {
        return {
            a: 1,
            b: 2
        }
    }
​
    const component1 = new myComponent()
    const component2 = new myComponent()
​
    component1.data.b = 5
    console.log(component2.data.b)
​
</script>
</body>
</html>

跨组件通信

是通过Vue空实例,作为连接$emit & $on,又称为中央通信
目前中央通信是解决兄弟间通信,祖父祖孙间通信的最佳方法,不仅限于此,也可以解决父组件子组件间的相互通信

  • 各组件可自己定义好组件内接收外部组件的消息事件即可,不用理会是哪个组件发过来;而对于发送事件的组件,亦不用理会这个事件到底怎么发送给我需要发送的组件。
  • Bus中央通信的方案各种情况下都可用,比较方便
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../vue.js"></script>
</head>
<body>
<div id="app">
    <Aaa></Aaa>
    <Bbb></Bbb>
</div>
<script>
    // Vue空实例 中央通信 用于连接$emit & $on
    let bus = new Vue()
​
    // 组件A
    Vue.component('Aaa', {
        template: `<div @click="aaa">我是A组件</div>`,
        methods: {
            aaa() {
                bus.$emit('is-selected') // 广播
            }
        }
    })
​
    // 组件B
    Vue.component('Bbb', {
        template: `<div>我是B组件</div>`,
        created() {
            bus.$on('is-selected', function() { // 接收/监听
                console.log('我是A组件传递过来的')
            })
        }
    })
​
    new Vue({
        el: '#app'
    })
</script>
</body>
</html>

单向数据流

数据从父组件传递给子组件,只能单向绑定。
在子组件内部不能直接修改父组件传递过来的数据。
注意:最新的Vue2.6版本,不会警告可以直接修改父组件传递过来的数据,简单查了一下没找到相关资料。按照2.0的理解去记就可以了,知道2.6这个特性即可。

不能直接改变父组件传递过来的数据

<div id="app">
    <custom-com :count="count"></custom-com>
</div>
<script>
    //子组件
    Vue.component('customCom', {
        props: ['count'],
        template: `<div>
<h2>我是自定义的组件</h2>
<p>{{ count }}</p>
<input type="button" value="改变count的值" @click="changeCount">
</div>`,
        methods: {
            changeCount() {
                this.count++
            }
        }
    })
​
    // 看做父组件
    new Vue({
        el: '#app',
        data: {
            count: 0
        }
    })
</script>

第一种修改方式:父组件传递过来的数据作为子组件局部的初始值

<div id="app">
    <custom-com :count="count"></custom-com>
</div>
<script>
    //子组件
    Vue.component('customCom', {
        props: ['count'],
        data() {
            return {
                increment: this.count
            }
        },
        template: `<div>
<h2>我是自定义的组件</h2>
<p>{{ increment }}</p>
<input type="button" value="改变count的值" @click="changeCount">
</div>`,
        methods: {
            changeCount() {
                this.increment++
            }
        }
    })
​
    // 看做父组件
    new Vue({
        el: '#app',
        data: {
            count: 0
        }
    })
</script>

第二种:通过computed

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../vue.js"></script>
</head>
<body>
<div id="app">
    <custom-com :count="count"></custom-com>
</div>
<script>
    //子组件
    Vue.component('customCom', {
        props: ['count'],
        data() {
            return {
                increment: this.count
            }
        },
        template: `<div>
<h2>我是自定义的组件</h2>
<p>{{ incrementCount }}</p>
<input type="button" value="改变count的值" @click="changeCount">
</div>`,
        methods: {
            changeCount() {
                this.increment++
            }
        },
        computed: {
            incrementCount() {
                return this.increment
            }
        }
    })
​
    // 看做父组件
    new Vue({
        el: '#app',
        data: {
            count: 0
        }
    })
</script>
</body>
</html>

Prop验证

我们可以为组件的 prop 指定验证要求

内置校验规则
String
Number
Boolean
Array
Object
Date
Function
Symbol

自定义校验规则
props: {
count: {
validator: function(value) {
return value < 10
}
}
},

示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../vue.js"></script>
</head>
<body>
<div id="app">
    <custom-com :count="count"></custom-com>
</div>
<script>
    //子组件
    Vue.component('customCom', {
        // props: {
        //     count: {
        //         type: [Number, String],
        //         default: 100
        //     }
        // },
        props: {
            count: {
               validator: function(value) {
                   return value < 10
               }
            }
        },
        data() {
            return {
                increment: this.count
            }
        },
        template: `<div>
<h2>我是自定义的组件</h2>
<p>{{ increment }}</p>
<input type="button" value="改变count的值" @click="changeCount">
</div>`,
        methods: {
            changeCount() {
                this.increment++
            }
        }
    })
​
    // 看做父组件
    new Vue({
        el: '#app',
        data: {
            count: 11
        }
    })
</script>
</body>
</html>

动态组件

多个组件可以使用同一个挂载点,动态切换

Component

<div id="app">
    <input type="button" value="切换到第1个组件" @click="tabComponent(1)">
    <input type="button" value="切换到第2个组件" @click="tabComponent(2)">
    <input type="button" value="切换到第3个组件" @click="tabComponent(3)">
    <component :is="current"></component>
</div>
<script>
​


// 第一个组件
const custom1 = Vue.component(‘custom1’, {
template: <div>我是第1个组件</div>
})
// 第二个组件
const custom2 = Vue.component(‘custom2’, {
template: <div>我是第2个组件</div>
})
// 第三个组件
const custom3 = Vue.component(‘custom3’, {
template: <div>我是第3个组件</div>
})

new Vue({
el: ‘#app’,
data: {
current: custom1
},
methods: {
tabComponent(index) {
if (index === 1) {
this.current = custom1
} else if(index ===2) {
this.current = custom2
} else {
this.current = custom3
}
}
}
})

keep-alive

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
它自身不会渲染一个 DOM 元素,也不会出现在父组件链中

<div id="app">
    <input type="button" value="切换到第1个组件" @click="tabComponent(1)">
    <input type="button" value="切换到第2个组件" @click="tabComponent(2)">
    <input type="button" value="切换到第3个组件" @click="tabComponent(3)">
    <keep-alive>
        <component :is="current"></component>
    </keep-alive>
</div>
<script>



// 第一个组件
const custom1 = Vue.component(‘custom1’, {
template: <div @click="changeBg">我是第1个组件</div>,
methods: {
changeBg(ev) {
ev.target.style.background = ‘orange’
}
}
})
// 第二个组件
const custom2 = Vue.component(‘custom2’, {
template: <div>我是第2个组件</div>
})
// 第三个组件
const custom3 = Vue.component(‘custom3’, {
template: <div>我是第3个组件</div>
})

new Vue({
el: ‘#app’,
data: {
current: custom1
},
methods: {
tabComponent(index) {
if (index === 1) {
this.current = custom1
} else if(index ===2) {
this.current = custom2
} else {
this.current = custom3
}
}
}
})

扩展
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值