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)


相关推荐

  • 拉格朗日乘数法_拉格朗日乘数法是求边界点吗

    拉格朗日乘数法_拉格朗日乘数法是求边界点吗原文地址:https://www.cnblogs.com/maybe2030/p/4946256.html阅读目录1.拉格朗日乘数法的基本思想 2.数学实例 3.拉格朗日乘数法的基本形态 4.拉格朗日乘数法与KKT条件   拉格朗日乘数法(LagrangeMultiplierMethod)之前听数学老师授课的时候就是一知半解,现在越发感觉拉格朗日乘数法应用的广泛性,…

    2022年10月22日
  • 使用gitolite搭建git服务器

    使用gitolite搭建git服务器使用gitolite搭建git服务器

  • javachar转int_c中int转char

    javachar转int_c中int转charchar类型的数据转换成int类型的数字。本能反应是这么写的。publicstaticvoidmain(String[]args){charc=’1′;//本能反应是这么写的。inti=c;//或者这么写inti1=(int)c;System.out….

  • 创建 Transact-SQL 作业步骤

    创建 Transact-SQL 作业步骤

  • IDEA设置背景为自定义照片「建议收藏」

    IDEA设置背景为自定义照片「建议收藏」一分钟教你把女朋友的照片设置成IDEA的背景图片【建议收藏】1.为什么写这篇文章?2.操作方法2.1.步骤12.2.步骤22.3.快捷操作一2.4.快捷操作二1.为什么写这篇文章?事情是这样的,在2021年6月10日早上我在CSDN上发布了文章《你真的懂Java怎么输出HelloWorld吗?》。这篇文章就如同标题一样,讲的是Java输出HelloWorld时源码的实现原理,本身再正常不过的一篇文章,但没想到的是。。十几天过去了,我却收到如下的评论??!!大家居然对我的IDEA背

  • 虚拟机与服务器桥接不能上网,vmware虚拟机桥接模式不能上网

    虚拟机与服务器桥接不能上网,vmware虚拟机桥接模式不能上网IntelliJIDEA的Jetty部署插件jetty相对于tomcat来说,启动速度非常快,方便调试.在idea的maven项目中,只需要在pom.xml配置文件中配置jetty的插件即可.全部:mvc无法找到资源昨天装了vs2015,但是第二步没有完成.今天急急忙忙的用13打开一个mvc的项目,但是添加的控制器怎么都不能访问.无法找到资源.说明:HTTP404.您正在查找的…

发表回复

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

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