前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue 使用props从父组件向子组件传递数据[通俗易懂]

Vue 使用props从父组件向子组件传递数据[通俗易懂]

作者头像
全栈程序员站长
发布2022-07-26 09:33:57
3.5K0
发布2022-07-26 09:33:57
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

Vue 使用props从父组件向子组件传递数据

通过props实现正向传递数据:父组件正向的向子组件传递数据或参数,子组件接收到后根据参数的不同来渲染不同的内容或者执行操作。 props使得父子之间形成了单向下行绑定:父级传递的数据的更新会向下流动到子组件中,但是反过来则不行。

(1)props的值有两种类型

使用选项props来声名需要从父级接收的数据,props的值有两种类型,一种是字符串数组,另外一种是对象。

1.数组

以字符串数组的形式列出props:

代码语言:javascript
复制
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
2.对象

如果希望每个 props 都有指定的类型的值。可以以对象形式列出 props,这些属性的名称和值分别是 props 各自的名称和类型:

代码语言:javascript
复制
props: { 
   
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object
}

关于传入的数据的类型,下面会详细介绍。

(2)传递动态或静态的props

给props传递一个静态的值:

代码语言:javascript
复制
<div id="app">
    <test title="我来自父组件!"></test>
</div>
<script> Vue.component('test', { 
     props: ['title'], template: '<div>{ 
    { title }}</div>' }); var app = new Vue({ 
     el: "#app", }) </script>

渲染的结果为:

代码语言:javascript
复制
<div id="app">
    <div>我来自父组件!</div>
</div>

props中传递的数据与data函数return的数据的主要区别是:props的数据来自父级,而data中的数据是组件自己的数据,作用域是组件本身。 这两种数据都可以用在模板template、计算属性computed和方法methods中。 由于HTML特性不区分大小写,当使用DOM模板时,驼峰命名的props名称要转为短横分隔命名:

代码语言:javascript
复制
<div id="app">
    <test title-one="我来自父组件!"></test>
</div>
<script> Vue.component('test', { 
     props: ['TitleOne'], template: '<div>{ 
    { TitleOne }}</div>' }); var app = new Vue({ 
     el: "#app", }) </script>

还可以使用v-bind传递动态的props值。这样的话,当父组件的数据变化时,也会实时更新到子组件:

代码语言:javascript
复制
<div id="app">
    <test v-bind:title="abc"></test>
</div>
<script> Vue.component('test', { 
     props: ['title'], template: '<div>{ 
    { title }}</div>' }); var app = new Vue({ 
     el: "#app", data:{ 
     abc:"我是标题!" } }) </script>

在上述两个示例中,我们传入的值都是字符串类型的,但实际上任何类型的值都可以传给props:

1.传入一个数字

静态传值,传入的值总会转化为字符串:

代码语言:javascript
复制
<div id="app">
    <test title="12"></test>
</div>
<script> Vue.component('test', { 
     props: ['title'], template: '<div v-on:click="dd">{ 
    { title }}</div>', methods:{ 
     dd:function(){ 
     console.log(typeof this.title)//string } } }); var app = new Vue({ 
     el: "#app", }) </script>

所以要想达到传数字的效果,要使用v-bind动态传值:

代码语言:javascript
复制
<div id="app">
    <test v-bind:title="abc"></test>
</div>
<script> Vue.component('test', { 
     props: ['title'], template: '<div v-on:click="dd">{ 
    { title }}</div>', methods:{ 
     dd:function(){ 
     console.log(typeof this.title)//number } } }); var app = new Vue({ 
     el: "#app", data:{ 
     abc:12 } }) </script>
2.传入一个布尔值

静态传值,传入的值总会转化为字符串。 也就是说,即使是”false”也会被当作true来处理,因为会被转化为字符串:

代码语言:javascript
复制
<div id="app">
    <test bool="false"></test><!--true-->
</div>
<script> Vue.component('test', { 
     props: ["bool"], template: '<div v-on:click="dd">我是:{ 
    { bool }}</div>', methods: { 
     dd: function () { 
     if (this.bool) { 
     console.log("true") }else{ 
     console.log("false") } } } }); var app = new Vue({ 
     el: "#app", }) </script>

所以要想传入正确的布尔值,要采用动态赋值:

代码语言:javascript
复制
<div id="app">
    <test v-bind:bool="false"></test><!--传入的bool的值为 false-->
</div>
<script> Vue.component('test', { 
     props: ["bool"], template: '<div v-on:click="dd">我是:{ 
    { bool }}</div>', methods: { 
     dd: function () { 
     if (this.bool) { 
     console.log("传入的bool的值为 true") }else{ 
     console.log("传入的bool的值为 false") } } } }); var app = new Vue({ 
     el: "#app", }) </script>
3.传入一个数组

静态传值,传入的值总会转化为字符串:

代码语言:javascript
复制
<div id="app">
    <test arr="[1,3,4]"></test>
</div>
<script> Vue.component('test', { 
     props: ["arr"], template: '<div v-on:click="dd">我是:{ 
    { arr }}</div>', methods: { 
     dd: function () { 
     console.log(typeof this.arr)//string } } }); var app = new Vue({ 
     el: "#app", }) </script>

传入正确的数组值,要采用动态赋值:

代码语言:javascript
复制
<div id="app">
    <test v-bind:arr="[1,3,4]"></test>
</div>
<script> Vue.component('test', { 
     props: ["arr"], template: '<div v-on:click="dd">我是:{ 
    { arr }}</div>', methods: { 
     dd: function () { 
     console.log(typeof this.arr)//object } } }); var app = new Vue({ 
     el: "#app", }) </script>

对于数组进行typeof类型检测,结果为object。

4.传入一个对象

静态传值,传入的值总会转化为字符串:

代码语言:javascript
复制
<div id="app">
    <test obj="{ 
    'one':1,'two':2}"></test>
</div>
<script> Vue.component('test', { 
     props: ["obj"], template: '<div v-on:click="dd">我是:{ 
    { obj }}</div>', methods: { 
     dd: function () { 
     console.log(typeof this.obj)//string } } }); var app = new Vue({ 
     el: "#app", }) </script>

传入正确的对象类型,要采用动态赋值:

代码语言:javascript
复制
<div id="app">
    <test v-bind:obj="{ 
    'one':1,'two':2}"></test>
</div>
<script> Vue.component('test', { 
     props: ["obj"], template: '<div v-on:click="dd">我是:{ 
    { obj }}</div>', methods: { 
     dd: function () { 
     console.log(typeof this.obj)//object } } }); var app = new Vue({ 
     el: "#app", }) </script>
5.传入一个对象的所有属性

如果想将一个对象的所有属性都传入子组件,可以使用v-bind直接传入一个对象:

代码语言:javascript
复制
<div id="app">
    <test v-bind:obj="obj111"></test>
</div>
<script> Vue.component('test', { 
     props: ["obj"], template: ` <div> <div>{ 
     { obj.one }}</div> <div>{ 
     { obj.two }}</div> </div>`, }); var app = new Vue({ 
     el: "#app", data: { 
     obj111: { 
     "one": 1, "two": 2 } } }) </script>

渲染结果为:

代码语言:javascript
复制
<div id="app">
    <div>
        <div>1</div>
        <div>2</div>
    </div>
</div>
(3)单向数据流

父级组件的数据发生更新时,子组件中所有的 props 都将会刷新为最新的值。 一般来说,不应该在子组件内部改变props的值,但是也有两种常见的在子组件内改变props的情形: A.这个 props 用来传递一个初始值。子组件将它作为初始值保存起来,在自己的作用域下可以随意使用和修改。在这种情况下,最好定义一个本地的 data 属性并将这个 props 用作其初始值:

代码语言:javascript
复制
props: ['initialCounter'],
data: function () { 
   
  return { 
   
    counter: this.initialCounter
  }
}

B.这个传入的值以原始值传入且需要进行转换。在这种情况下,最好使用这个传入的原始值来定义一个计算属性:

代码语言:javascript
复制
props: ['size'],
computed: { 
   
  normalizedSize: function () { 
   
    return this.size.trim().toLowerCase()
  }
}

注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 props 来说,在子组件中改变这个对象或数组本身将会影响到父组件中的数据:

代码语言:javascript
复制
<div id="app">
    <test v-bind:obj="obj111"></test>
    <div>这是父级:{
  
  {obj111.one}}</div>
</div>
<script> Vue.component('test', { 
     props: ["obj"], template: '<div>这是子组件:{ 
    {changeone}}</div>', computed:{ 
     changeone:function(){ 
     return ++this.obj.one } } }); var app = new Vue({ 
     el: "#app", data: { 
     obj111: { 
     "one": 1 } } }) </script>

渲染结果为:

代码语言:javascript
复制
<div id="app">
    <div>这是子组件:2</div>
    <div>这是父级:2</div>
</div>

在子组件中,通过计算属性,将传入的值增加了1,因为对象是通过引用传入的,父子组件中的数据指向同一个内存空间。所以也会改变父组件中的数据。采用的是前置递增,子组件和父组件中的值都变为了2。

(4)数据验证

之前提到过props选项的值还可以是一个对象,可以用来作为数据验证。 可以为传入组件的props指定类型验证,例如:

代码语言:javascript
复制
Vue.component('my-component', { 
   
  props: { 
   
    // 必须是数字类型
    propA: Number,
    // 必须是数字或者字符串类型
    propB: [String, Number],
    // 必填的字符串
    propC: { 
   
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: { 
   
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: { 
   
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () { 
   
        return { 
    message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: { 
   
      validator: function (value) { 
   
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

注意那些 props 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的。 type 可以是下列原生构造函数中的一个:

String Number Boolean Array Object Date Function Symbol

type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。 例如,给定下列的构造函数:

代码语言:javascript
复制
function Person (firstName, lastName) { 
   
  this.firstName = firstName
  this.lastName = lastName
}

你可以使用:

代码语言:javascript
复制
Vue.component('blog-post', { 
   
  props: { 
   
    author: Person
  }
})

来验证传入的author的值是否是通过 new Person 创建的。

(5)非props特性

一个非 props 特性是指传向一个组件,但是该组件并没有相应的props定义的特性。 组件可以接受任意的特性,而这些特性会被添加到这个组件的根元素上。 传入的特性可能会替换或者合并已有的特性: <test> 的模板是这样的:

代码语言:javascript
复制
  Vue.component('test', {
        template: '<input type="data" class="left">',
    });

在使用的时候:

代码语言:javascript
复制
<test class="up"></test>

对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。 所以如果传入 type=“text” 就会替换掉 type=“date” 。 但是class 和 style 特性会把两边的值合并起来,从而得到最终的值:class=“left up”。

参考: 1.Vue.js官方文档 2.《Vue.js实战》

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/128014.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年4月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Vue 使用props从父组件向子组件传递数据
    • (1)props的值有两种类型
      • (2)传递动态或静态的props
        • 1.传入一个数字
        • 2.传入一个布尔值
        • 3.传入一个数组
        • 4.传入一个对象
        • 5.传入一个对象的所有属性
        • (3)单向数据流
        • (4)数据验证
        • (5)非props特性
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档