6 props校验完整写法
6.1.语法
props: { 校验的属性名: { type: 类型, // Number String Boolean ... required: true, // 是否必填 default: 默认值, // 默认值 validator (value) { // 自定义校验逻辑 return 是否通过校验 } } },
6.2.代码实例
<script> export default { // 完整写法(类型、默认值、非空、自定义校验) props: { w: { type: Number, //required: true, default: 0, validator(val) { // console.log(val) if (val >= 100 || val <= 0) { console.error('传入的范围必须是0-100之间') return false } else { return true } }, }, }, } </script>
6.3.注意
1.default和required一般不同时写(因为当时必填项时,肯定是有值的)
2.default后面如果是简单类型的值,可以直接写默认。如果是复杂类型的值,则需要以函数的形式return一个默认值
7 props&data、单向数据流
7.1.共同点
都可以给组件提供数据
7.2.区别
- data 的数据是自己的 → 随便改
- prop 的数据是外部的 → 不能直接改,要遵循 单向数据流
7.3.单向数据流:
父级props 的数据更新,会向下流动,影响子组件。这个数据流动是单向的
7.4.代码演示
App.vue
<template> <div class="app"> <BaseCount></BaseCount> </div> </template> <script> import BaseCount from './components/BaseCount.vue' export default { components:{ BaseCount }, data(){ }, } </script> <style> </style>
BaseCount.vue
<template> <div class="base-count"> <button @click="count--">-</button> <span>{{ count }}</span> <button @click="count++">+</button> </div> </template> <script> export default { // 1.自己的数据随便修改 (谁的数据 谁负责) data () { return { count: 100, } }, // 2.外部传过来的数据 不能随便修改 //props: { // count: { // type: Number, // }, //} } </script> <style> .base-count { margin: 20px; } </style>
7.5.口诀
谁的数据谁负责
8 综合案例-组件拆分
8.1.需求说明
- 拆分基础组件
- 渲染待办任务
- 添加任务
- 删除任务
- 底部合计 和 清空功能
- 持久化存储
8.2.拆分基础组件
咱们可以把小黑记事本原有的结构拆成三部分内容:头部(TodoHeader)、列表(TodoMain)、底部(TodoFooter)
9 综合案例-列表渲染
思路分析:
- 提供数据:提供在公共的父组件 App.vue
- 通过父传子,将数据传递给TodoMain
- 利用v-for进行渲染
10 综合案例-添加功能
思路分析:
- 收集表单数据 v-model
- 监听时间 (回车+点击 都要进行添加)
- 子传父,将任务名称传递给父组件App.vue
- 父组件接受到数据后 进行添加 unshift(自己的数据自己负责)
11 综合案例-删除功能
思路分析:
- 监听时间(监听删除的点击)携带id
- 子传父,将删除的id传递给父组件App.vue
- 进行删除 filter (自己的数据自己负责)
12 综合案例-底部功能及持久化存储
思路分析:
- 底部合计:父组件传递list到底部组件 —>展示合计
- 清空功能:监听事件 —> 子组件通知父组件 —>父组件清空
- 持久化存储:watch监听数据变化,持久化到本地
13 非父子通信-event bus 事件总线
13.1.作用
非父子组件之间,进行简易消息传递。(复杂场景→ Vuex)
13.2.步骤
- 创建一个都能访问的事件总线 (空Vue实例)
import Vue from 'vue' const Bus = new Vue() export default Bus
A组件(接受方),监听Bus的 $on事件
created () { Bus.$on('sendMsg', (msg) => { this.msg = msg }) }
B组件(发送方),触发Bus的$emit事件
Bus.$emit('sendMsg', '这是一个消息')
13.3.代码示例
EventBus.js
import Vue from 'vue' const Bus = new Vue() export default Bus
BaseA.vue(接受方)
<template> <div class="base-a"> 我是A组件(接收方) <p>{{msg}}</p> </div> </template> <script> import Bus from '../utils/EventBus' export default { data() { return { msg: '', } }, } </script> <style scoped> .base-a { width: 200px; height: 200px; border: 3px solid #000; border-radius: 3px; margin: 10px; } </style>
BaseB.vue(发送方)
<template> <div class="base-b"> <div>我是B组件(发布方)</div> <button>发送消息</button> </div> </template> <script> import Bus from '../utils/EventBus' export default { } </script> <style scoped> .base-b { width: 200px; height: 200px; border: 3px solid #000; border-radius: 3px; margin: 10px; } </style>
App.vue
<template> <div class="app"> <BaseA></BaseA> <BaseB></BaseB> </div> </template> <script> import BaseA from './components/BaseA.vue' import BaseB from './components/BaseB.vue' export default { components:{ BaseA, BaseB } } </script> <style> </style>
13.4.总结
1.非父子组件传值借助什么?
2.什么是事件总线
3.发送方应该调用事件总线的哪个方法
4.接收方应该调用事件总线的哪个方法
5.一个组件发送数据,可不可以被多个组件接收
14 非父子通信-provide&inject
14.1.作用
跨层级共享数据
14.2.场景
14.3.语法
- 父组件 provide提供数据
export default { provide () { return { // 普通类型【非响应式】 color: this.color, // 复杂类型【响应式】 userInfo: this.userInfo, } } }
2.子/孙组件 inject获取数据
export default { inject: ['color','userInfo'], created () { console.log(this.color, this.userInfo) } }
14.4.注意
- provide提供的简单类型的数据不是响应式的,复杂类型数据是响应式。(推荐提供复杂类型数据)
- 子/孙组件通过inject获取的数据,不能在自身组件内修改