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

Vueprop

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

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

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

(1)props的值有两种类型

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

1.数组

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

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
2.对象

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

props: { 
   
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object
}

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

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

给props传递一个静态的值:

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

渲染的结果为:

<div id="app">
    <div>我来自父组件!</div>
</div>

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

<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值。这样的话,当父组件的数据变化时,也会实时更新到子组件:

<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.传入一个数字

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

<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动态传值:

<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来处理,因为会被转化为字符串:

<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>

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

<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.传入一个数组

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

<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>

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

<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.传入一个对象

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

<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>

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

<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直接传入一个对象:

<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>

渲染结果为:

<div id="app">
    <div>
        <div>1</div>
        <div>2</div>
    </div>
</div>
(3)单向数据流

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

props: ['initialCounter'],
data: function () { 
   
  return { 
   
    counter: this.initialCounter
  }
}

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

props: ['size'],
computed: { 
   
  normalizedSize: function () { 
   
    return this.size.trim().toLowerCase()
  }
}

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

<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>

渲染结果为:

<div id="app">
    <div>这是子组件:2</div>
    <div>这是父级:2</div>
</div>

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

(4)数据验证

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

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 来进行检查确认。
例如,给定下列的构造函数:

function Person (firstName, lastName) { 
   
  this.firstName = firstName
  this.lastName = lastName
}

你可以使用:

Vue.component('blog-post', { 
   
  props: { 
   
    author: Person
  }
})

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

(5)非props特性

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

  Vue.component('test', {
        template: '<input type="data" class="left">',
    });

在使用的时候:

<test class="up"></test>

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java 优先级队列_JAVA 队列

    java 优先级队列_JAVA 队列优先级队列是比栈和队列更专用的结构,在多数情况下都非常有用。优先级队列像普通队列一样,有一个队头和队尾,并且也是从队头移除数据。优先级队列中,数据按关键词有序排列,插入新数据的时候,会自动插入到合适的位置保证队列有序。举个例子来说,一组整型数,如果使用优先级队列的话,不管队列之前放入的数据如何,后面添加进去的数据总会被按照升序或者降序排列,当然这个只是优先级队列最基本的使用,在实际生产中可能有…

    2022年9月15日
    2
  • ListView装上拉电阻下拉刷新

    ListView装上拉电阻下拉刷新

    2022年1月13日
    48
  • 最详细的windows10系统封装教程

    最详细的windows10系统封装教程自定义封装(定制)windows10教程详细记录如何去定制、封装属于自己的windows10操作系统,跟着本教程走,相信你也能成功!关于本教程及用到的工具的声明本教程所运用到的软件都来自于网

    2022年7月4日
    30
  • 基于灰色关联度分析法_灰色关联度分析法的优缺点

    基于灰色关联度分析法_灰色关联度分析法的优缺点本文介绍了利用灰色关联度分析方法分析了数据之间的关联度。

    2025年8月6日
    2
  • vue.js单页应用_vue嵌入第三方页面

    vue.js单页应用_vue嵌入第三方页面今天我们看看VUE怎么开发单页面应用,VUE提供了脚手架vue-cli,通过这个可以很轻松的创建VUE单页面应用,1.创建VUE项目  首先确保电脑上安装了NODE.JS, 在创建项目的目录下,打开CMD命令行,执行脚手架命令,安装脚手架cli. #全局安装vue-cli,一定要在全局模式下安装vue-cli,否则无法使用vue命令npminstall-gvue…

    2022年10月13日
    4
  • docker部署vue项目_docker部署java

    docker部署vue项目_docker部署java第一步:vue项目打包成dist。npmrunbuild第二步:构建Dockerfile#设置基础镜像,这里使用最新的nginx镜像,前面已经拉取过了FROMnginx#将dist文件中的内容复制到/usr/share/nginx/html/这个目录下面COPYdist//usr/share/nginx/html/第三步:安装nginxdockerpullnginxdockerrun–namenginx-d-p4030:8.

    2022年10月19日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号