vue3的props和defineProps

news2024/10/6 19:30:04

文章目录

    • 1. Props 声明
      • 1.1 props用字符串数组来声明
        • Blog.vue
        • BlogPost.vue
      • 1.2 props使用对象来声明
        • Blog.vue
        • BlogPost.vue
    • 2. 传递 prop 的细节
      • 2.1 Prop 名字格式
      • 2.1 静态Prop & 动态 Prop
        • 静态prop
        • 动态prop
          • 示例
            • Blog.vue
            • BlogPost.vue
      • 2.3 传递不同的值类型
        • Number
        • Boolean
        • Array
        • Object
      • 2.4 使用一个对象绑定多个 prop
        • Blog.vue
        • BlogPost.vue
    • 3. 单向数据流(重要)
      • 3.1 更改对象 / 数组类型的 props
        • Blog.vue
        • BlogPost.vue
    • 4. Prop 校验
      • 4.1 运行时类型检查
    • 5. Boolean 类型转换
      • Blog.vue
      • BlogPost.vue

1. Props 声明

  • 一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute
  • props 需要使用 props 选项来定义

1.1 props用字符串数组来声明

看上去跟vue2没什么区别,就是先引入组件,然后注册组件,然后就使用组件。接着绑定属性。

Blog.vue

<template>
    <div>
        <h1>Blog组件</h1>
        <blog-post title="学习vue3"/>
    </div>
</template>

<script >
    import BlogPost from './BlogPost.vue'
    export default {
        name: 'Blog',
        components:{
            BlogPost
        }
    }

</script>

<style lang="scss"></style>

BlogPost.vue

<template>
    <h3>{{ title }}</h3>
</template>

<script>

    export default {
        name: 'BlogPost',
        props: ['title']
    }

</script>

<style lang="scss"></style>

1.2 props使用对象来声明

  • key 是 prop 的名称,而值则是该 prop 预期类型的构造函数
  • 如果在使用时,传递了错误的类型,会在浏览器控制台中抛出警告

Blog.vue

<template>
    <div>
        <h1>Blog组件</h1>
        <blog-post title="学习vue3" :likes="3"/>
    </div>
</template>

<script >
    import BlogPost from './BlogPost.vue'
    export default {
        name: 'Blog',
        components:{
            BlogPost
        }
    }

</script>

<style lang="scss"></style>

BlogPost.vue

<template>
    <h3>{{ title }}</h3>
    <span>{{ likes }}</span>
</template>

<script>

export default {
    name: 'BlogPost',
    props: {
        title: String,
        likes: Number
    }
}

</script>

<style lang="scss"></style>

2. 传递 prop 的细节

2.1 Prop 名字格式

  • 定义prop的名字时 ,建议使用 camelCase 形式(驼峰命名,首字母小写)
  • 向子组件传递 props 时,可以使用 camelCase 形式,但通常使用kebab-case形式(短横线形式)
  • 定义组件名时,建议使用PascalCase形式(驼峰命名,但首字母大写)

2.1 静态Prop & 动态 Prop

静态prop

<BlogPost title="My journey with Vue" />

动态prop

可以将组件中定义的属性值(响应式数据)传给子组件,当这些属性值发生变化时,子组件也会更新重新渲染

<!-- 根据一个变量的值动态传入 -->
<BlogPost :title="post.title" />

<!-- 根据一个更复杂表达式的值动态传入 -->
<BlogPost :title="post.title + ' by ' + post.author.name" />
示例

在这里插入图片描述

Blog.vue
<template>
    <div>
        <h1>Blog组件</h1>
        <button @click="addLike">addLike</button>
        <blog-post title="学习vue3" :likes="likes"/>
    </div>
</template>

<script >
    import BlogPost from './BlogPost.vue'
    export default {
        name: 'Blog',
        components:{
            BlogPost
        },
        data() {
            return {
                likes: 0
            }
        },
        methods: {
            addLike() {
                this.likes ++
            }
        }
    }

</script>

<style lang="scss">

</style>
BlogPost.vue
<template>
    <h3>{{ title }}</h3>
    <span>{{ likes }}</span>
</template>

<script>

export default {
    name: 'BlogPost',
    props: {
        title: String,
        likes: Number
    }
}

</script>

<style lang="scss"></style>

2.3 传递不同的值类型

  • 任何类型的值都可以作为 props 的值被传递。
  • 使用 v-bind绑定的值 将视为 js表达式

Number

<!-- 虽然 `42` 是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :likes="42" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :likes="post.likes" />

Boolean

注意会隐式转换,和 使用 v-bind绑定的值 将视为 js表达式

<!-- 仅写上 prop 但不传值,会隐式转换为 `true` -->
<BlogPost is-published />

<!-- 虽然 `false` 是静态的值,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :is-published="false" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :is-published="post.isPublished" />

Array

<!-- 虽然这个数组是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :comment-ids="[234, 266, 273]" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :comment-ids="post.commentIds" />

Object

<!-- 虽然这个对象字面量是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :author="{name: 'Veronica', company: 'Veridian Dynamics'}" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :author="post.author" />

2.4 使用一个对象绑定多个 prop

可以使用没有参数的 v-bind,即只使用 v-bind 而非 :prop-name。这样就可以将一个对象的所有属性都当作 props 传入

在这里插入图片描述

Blog.vue

<template>
    <div>
    
        <h1>Blog组件</h1>
        
        <blog-post v-bind="post"/>
        
        <blog-post :title="post.title" :likes="post.likes"/>
        
    </div>
</template>

<script >
    import BlogPost from './BlogPost.vue'
    export default {
        name: 'Blog',
        components:{
            BlogPost
        },
        data() {
            return {
                post: {
                    likes: 3,
                    title: '学习vue3'
                }
            }
        }
    }

</script>

<style lang="scss"></style>

BlogPost.vue

<template>
    <h3>{{ title }}</h3>
    <span>{{ likes }}</span>
</template>

<script>

export default {
    name: 'BlogPost',
    props: {
        title: String,
        likes: Number
    }
}

</script>

<style lang="scss"></style>

3. 单向数据流(重要)

  • 所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。

  • 每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告

    export default {
      props: ['foo'],
      created() {
        // ❌ 警告!prop 是只读的!
        this.foo = 'bar'
      }
    }
    
  • 子组件想修改prop,可以使用 “变通的手段来更改prop”(不是真正的修改)

    • prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可:

      export default {
        props: ['initialCounter'],
        data() {
          return {
            // 计数器只是将 this.initialCounter 作为初始值
            // 像下面这样做就使 prop 和后续更新无关了
            counter: this.initialCounter
          }
        }
      }
      
    • 需要对传入的 prop 值做进一步的转换。在这种情况中,最好是基于该 prop 值定义一个计算属性

      export default {
        props: ['size'],
        computed: {
          // 该 prop 变更时计算属性也会自动更新
          normalizedSize() {
            return this.size.trim().toLowerCase()
          }
        }
      }
      

3.1 更改对象 / 数组类型的 props

对 象数组 作为 props 被传入时,虽然子组件无法更改 props 绑定,但仍然可以更改对象或数组内部的值

  • 在最佳实践中,你应该尽可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合

  • 在大多数场景下,子组件应该抛出一个事件来通知父组件做出改变

在这里插入图片描述

Blog.vue

<template>
    <div>
        <h1>Blog组件</h1>
        <blog-post :post="post" @addLiking="addLiking"/>
    </div>
</template>

<script >
    import BlogPost from './BlogPost.vue'
    export default {
        name: 'Blog',
        components:{
            BlogPost
        },
        data() {
            return {
                post: {
                    likes: 3,
                    title: '学习vue3',
                    tags: ['java','spring','vue','ps']
                },
                
            }
        },
        methods: {
            addLiking(){
                this.post.likes += 2
            }
        }
    }

</script>

<style lang="scss"></style>

BlogPost.vue

  • 父组件通过props传递过来post
  • 子组件中直接修改通过props传过来的post(对象)里面内部的属性
  • 子组件中直接修改通过props传过来的post.tags(数组)里面内部的属性
<template>
    <h3>{{ post.title }}</h3>
    <span>{{ post.likes }}</span> 

    <br/>

    <span v-for="tag,idx in post.tags" :key="idx">{{ tag }}、</span>
    
    <br/>

    <button @click="addLike">addLike + 1</button>
    <button @click="emitLike">emitLike + 2</button>

    <br/>

    <button @click="post.tags[3] = 'redis'">changeArr</button>
    
</template>

<script>

export default {
    name: 'BlogPost',
    props: {
        post: Object
    },
    methods: {
        addLike() {
            this.post.likes++
        },
        emitLike() {
            this.$emit('addLiking')
        }
    }
}

</script>

<style lang="scss"></style>

4. Prop 校验

可以向 props 选项提供一个带有 props 校验选项的对象。

  • 所有 prop 默认都是可选的,除非声明了 required: true
  • 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined
    • Boolean 类型的未传递 prop 将被转换为 false!!!(但是,可以通过default来修改,比如:default:undefined。)。
  • 如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值。
export default {

  props: {
  
    // 基础类型检查
    //(给出 `null` 和 `undefined` 值则会跳过任何类型检查)
    propA: Number,
    
    // 多种可能的类型
    propB: [String, Number],
    
    // 必传,且为 String 类型
    propC: {
      type: String,
      required: true
    },
    
    // Number 类型的默认值
    propD: {
      type: Number,
      default: 100
    },
    
    // 对象类型的默认值
    propE: {
      type: Object,
      // 对象或者数组应当用工厂函数返回。
      // 工厂函数会收到组件所接收的原始 props
      // 作为参数
      default(rawProps) {
        return { message: 'hello' }
      }
    },
    
    // 自定义类型校验函数
    propF: {
      validator(value) {
        // The value must match one of these strings
        return ['success', 'warning', 'danger'].includes(value)
      }
    },
    
    // 函数类型的默认值
    propG: {
      type: Function,
      // 不像对象或数组的默认,这不是一个
      // 工厂函数。这会是一个用来作为默认值的函数
      default() {
        return 'Default function'
      }
    }
    
  }
}

4.1 运行时类型检查

校验选项中的 type 可以是下列这些原生构造函数,也可以是自定义的类或构造函数,Vue 将会通过 instanceof 来检查类型是否匹配。

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

5. Boolean 类型转换

声明为 Boolean 类型的 props 有特别的类型转换规则

在这里插入图片描述

Blog.vue

  • 虽然diabled属性被声明为了Boolean类型,但是,如果传一个字符串过去,仍然就是字符串。
<template>
    <div>
        <h1>Blog组件</h1>
        <blog-post disabled/> <br/>
        <blog-post disabled/> <br/>
        <blog-post disabled="false"/> <br/>
        <blog-post disabled="false1"/> <br/>
        <blog-post :disabled="false"/>
    </div>
</template>

<script >
    import BlogPost from './BlogPost.vue'
    export default {
        name: 'Blog',
        components:{
            BlogPost
        },
        data() {
            return {}
        }
    }

</script>

<style lang="scss"></style>

BlogPost.vue

<template>
    
    {{ disabled }}

</template>

<script>

export default {
    name: 'BlogPost',
    props: {
        disabled:Boolean
    }
}

</script>

<style lang="scss"></style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/477028.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java笔试强训 11】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;最近公共…

算法记录 | Day46 动态规划

139.单词拆分 思路&#xff1a; 1.确定dp数组以及下标的含义 dp[i] : 字符串长度为i的话&#xff0c;dp[i]为true&#xff0c;表示可以拆分为一个或多个在字典中出现的单词。 2.确定递推公式 如果 s[0: j] 可以拆分为单词&#xff08;即 dp[j] True&#xff09;&#xff…

Linux RHCE解题方法

目录 安装和配置Ansible 创建和运行Ansible临时命令 安装软件包 使用RHEL系统角色 使用 Ansible Galaxy 安装角色 创建和使用角色 从 Ansible Galaxy 使用角色 创建和使用逻辑卷 生成主机文件 修改文件内容 创建 Web 内容目录 生成硬件报告 创建密码库 创建用户帐…

C++中stringstream类详解

本文主要介绍 C 编程语言中 stringstream 类的相关知识&#xff0c;同时通过示例代码介绍 stringstream 类的使用方法。 1 概述 <sstream> 定义了三个类&#xff1a;istringstream、ostringstream 和 stringstream&#xff0c;分别用来进行流的输入、输出和输入输出操作…

快速傅里叶变换FFT学习笔记

点值表示法 我们正常表示一个多项式的方式&#xff0c;形如 A ( x ) a 0 a 1 x a 2 x 2 . . . a n x n A(x)a_0a_1xa_2x^2...a_nx^n A(x)a0​a1​xa2​x2...an​xn&#xff0c;这是正常人容易看懂的&#xff0c;但是&#xff0c;我们还有一种表示法。 我们知道&#xf…

java结束当前循环

在 Java中&#xff0c;当我们要结束一个循环时&#xff0c;通常会使用循环变量的实现类来结束&#xff0c;但在实际开发中&#xff0c;我们经常会遇到某个循环结束后需要进行其他的操作的情况。此时&#xff0c;就需要使用循环变量来结束当前循环。 1、创建一个新的类&#xff…

数据结构_双链表、循环链表、静态链表

目录 1. 双链表 1.1 双链表的初始化 1.2 双链表的插入操作 1.3 双链表的删除操作 1.4 双链表的遍历 2. 循环链表 2.1 循环单链表 2.2 循环双链表 3. 静态链表 4. 顺序表和链表的比较 5. 相关练习 1. 双链表 单链表结点中只有一个指向其后继的指针&#xff0c;使得单…

电子电气架构——车辆E/E架构软硬件解耦

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 人只有在举棋不定,无从把握的时候才感到疲惫。只有去行动就能获得解放,哪怕做的不好也比无所作为强! 本文主要介绍车辆E/E架构常识,主要涉及内容是行业最…

Python实现LBP纹理提取

1、什么是LBP纹理特征&#xff1f; LBP&#xff08;Local Binary Patterns&#xff0c;局部二值模式&#xff09;是提取局部特征作为判别依据的&#xff0c;一种有效的纹理描述算子&#xff0c;度量和提取图像局部的纹理信息。它具有旋转不变性和灰度不变性等显著的优点&#…

uniapp中使用vuex(解决uniapp无法在data和template中获取vuex数据问题)

uniapp中使用vuex&#xff08;解决uniapp无法在data和template中获取vuex数据问题&#xff09; 1. uniapp中引入vuex2. uniapp中使用vuex3. 解决uniapp无法在data和template中获取vuex数据问题 1. uniapp中引入vuex 1 .在根目录下新建文件夹store,在此目录下新建index.js文件&…

第五章——动态规划3

蒙德里安的梦想 我们在黑框内横着放红框&#xff0c;我们发现当横向小方格摆好之后&#xff0c;纵向小方格只能一次纵向摆好&#xff0c;即纵向小方格只有一种方案&#xff0c;即整个摆放小方格的方案数等于横着摆放小方格的方案数 f[i,j]表示的是现在要在第i列摆&#xff0c;j…

代码随想录Day64(一刷完结)

今天学习单调栈解决最后一道题 84.柱状图中的最大矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 1: 输入&#xff1a;heights [2,1,5,6,…

C++中的list容器

文章目录 list的介绍list的使用list的构造list iterator的使用list capacitylist元素访问list modifierslist的迭代器失效 list与vector的对比 list的介绍 list是可以在常数范围内的任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代&#xff1b;   …

FFMPEG中的filter使用二

上一篇我们在使用滤镜时是手动创建各种滤镜&#xff0c;然后根据处理链路手动链接不同的过滤器&#xff0c;有助于我们理解滤镜的流程。这一篇我们使用参数形式&#xff0c;让ffmpeg自动帮我们创建和链接过滤器&#xff0c;这样可以减少代码量&#xff0c;同时我们可以先使用参…

学系统集成项目管理工程师(中项)系列15_质量管理

1. 质量&#xff08;Quality&#xff09;的定义 1.1. 反应实体满足主体明确和隐含需求的能力的特性总和 1.2. 明确需求是指在标准、规范、图样、技术要求、合同和其他文件中用户明确提出的要求与需要 1.3. 隐含需求是指用户和社会通过市场调研对实体的期望以及公认的、不必明…

thinkphp路由,请求和响应

文章目录 定义获取路由后面的参数跨域请求请求响应 定义 thinkphp定义路由一般在route路由下的app.php中 下面这是一个简单的路由 Route::rule(admin/login,/app/controller/Admin/login)->middleware(\app\middleware\MyMiddleware::class);该路由表示当访问admin/login时…

人工智能课程笔记(7)强化学习(基本概念 Q学习 深度强化学习 附有大量例题)

文章目录 1.强化学习与深度学习的区别2.强化学习中的基本概念3.强化学习、有监督学习和无监督学习的区别4.强化学习的特点5.离散马尔可夫过程6.马尔可夫奖励过程7.马尔可夫决策过程8.策略学习8.1.策略学习概念8.2.策略评估与贝尔曼方程 9.强化学习的最优策略求解10.基于价值的强…

K8s基础1——发展起源、资源对象、集群架构

文章目录 一、发展起源二、资源对象2.1 集群类2.2 应用类2.3 存储类2.4 安全类 三、集群架构 一、发展起源 K8s官方文档 K8s怎么来的&#xff1f; 十几年来&#xff0c;谷歌内部使用的大规模集群管理系统是Brog&#xff0c;基于容器技术实现了资源管理的自动化和跨多个数据中心…

基于Python的连锁超市收银系统的开发与研究_kaic

基于Python的连锁超市收银系统的开发与研究 摘要&#xff1a;近几年来&#xff0c;国内的连锁超市收银系统也在不断的发展与完善&#xff0c;超市收银系统是一个超市管理的核心&#xff0c;他决定了超市的安全性。目前&#xff0c;大大小小的超市基本上由传统的人工管理逐渐过渡…

IT 面试手册 - 序

IT 面试手册 - 序 前言 首先&#xff0c;感谢你阅读我的文章。作为在计算机互联网行业摸爬滚打近十载的半个过来人&#xff0c;在这里分享一些关于求职面试和自我提升的心得感悟&#xff0c;希望能够给你一些启发。 背景 对于 IT 从业者来说&#xff0c;当今这个时代&#x…