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实战》

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 反射getmethod参数_java通过反射获取属性值

    反射getmethod参数_java通过反射获取属性值1、forName方法forName是一个静态方法,其作用:通过调用来获取类名对应的Class对象,同时将Class对象加载进来。如果将类名保存在字符串(如xml)中,就可以在程序运行时,动态调用加载。注意:只有调用的参数是类名或者方法时,才可用。2、newInstance()方法作用:将对象实例化。返回类型为Object。与new的区别在于,new可以带参,而newInstance()不可以,…

  • CodeBlocks控制台中文乱码

    CodeBlocks控制台中文乱码中文乱码是个老问题了,涉及乱码的问题无非是编码不统一造成的;涉及编码的地方常见有:1.源文件本身编码2.编译器读取源文件编码3.数据编码(数据库,IO文件等)4.执行输出编码&amp;nbsp;知道乱码的原因有利于解决乱码问题,这些原因在哪个IDE都是通用的&amp;nbsp;关于codeblock这款IDE,这里…

  • Android面试题集锦(2019最新总结)

    一、20182018年的年假休完了,正式进入2019的工作中。也该规划一下自己的职业生涯了;是选择继续从事Android(android的话已经火了几年了,现在算是进入寒冬了,需要考虑清楚)?还是从事Java方面?还是改管理方面?如果继续从事Android方面,那么就要往资深的发展(需要搞FrameWork层,需要拿起C/C++),2019年了需要换个新的环境或者需要换个更好的平台;那还得…

  • react-router4的按需加载实践(基于create-react-app和Bundle组件)

    react-router4的按需加载实践(基于create-react-app和Bundle组件)

  • 权限表和菜单表_sqlserver赋予用户表权限

    权限表和菜单表_sqlserver赋予用户表权限selectm.*     fromt_menum     wherem.state=’1′      and((menu_type=1andexists        (select1          fromv_user_menub          wherem.menu_id…

  • Mysql Workbench使用教程

    Mysql Workbench使用教程<1>MySQLWorkbenchMySQLWorkbench为数据库管理员、程序开发者和系统规划师提供可视化的Sql开发、数据库建模、以及数据库管理功能。<2>.MySQLWorkbench的下载和安装(1)安装最新MySql时,有是否安装MySqlWorkbench的选项,可选择安装。(2)可以独立安装MySqlWorkbench…

发表回复

您的电子邮箱地址不会被公开。

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