Vue 中的 Props 与 Data 细微差别,你知道吗?

更新日期: 2020-01-01阅读: 1.8k标签: props

vue提供了两种不同的存储变量:props和data。

这些方法一开始可能会让人感到困惑,因为它们做的事情很相似,而且也不清楚什何时使用props,何时使用data。

那么props和data有什么区别呢?

data是每个组件的私有内存,可以在其中存储需要的任何变量。props是将数据从父组件传递到子组件的方式。

在本文中,我们将学习到:

  • 什么是props,为什么这些数据只向下流动,而不是向上
  • data 选项的用途
  • 响应式是什么
  • 如何避免 props 和 data 之间的命名冲突
  • 如何将 props 和 data 结合使用


什么是 props

在Vue中,props(或properties)是我们将数据从父组件向下传递到其子组件的方式。

当我们使用组件构建应用程序时,最终会构建一个称为树的数据结构。 类似于家谱,具有:

  • 父母
  • 孩子
  • 祖先
  • 子孙

数据从根组件(位于最顶端的组件)沿着树向下流动。就像基因是如何代代相传的一样,父组件也会将自己的props传给了他们的孩子。

在Vue中,我们在代码的<template>中向组件添加了一些props

<template>
  <my-component cool-prop="hello world"></my-component>
</template>

在这个例子中,我们传递一个名为color-prop prop,其值为“hello world”。我们能够从my-component内部访问这个值。

然而,当我们从组件内部访问props时,我们并不拥有它们,所以我们不能更改它们(就像你不能改变你父母给你的基因一样)。

注意:虽然可以更改组件中的属性,但这是一个非常糟糕的主意。最终还会更改父类正在使用的值,这可能会导致很多混淆。

但是有些情况我们需要改变变量,所以 data 就派上用场了。


什么是 data ?

data是每个组件的内存,这是存储数据和希望跟踪的任何其他变量的地方。

如果我们正在构建一个计数器应用程序,我们将需要跟踪计数,因此我们将向我们的data添加一个count:

<template>
  <div>
    {{ count }}
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>
------------------------------------------
export default {
  name: 'Counter',
  data() {
    return {
      // Initialized to zero to begin
      count: 0,
    }
  },
  methods: {
    increment() {
      this.count += 1;
    },
    decrement() {
      this.count -= 1;
    }
  }
}

此处的data是私有的,仅供组件本身使用,其他组件不能访问它。

注意:理论上是其它组件是不能访问这些数据,但实际是可以的。但是出于同样的原因,这样做是非常糟糕的

如果需要向组件传递数据,可以使用props向下传递数据(传递给子组件),或者使用事件向上传递数据(传递给父组件)。


props 和 data 都是响应式的

使用 Vue,我们不需要过多地考虑组件什么时候会更新,Vue 会自动帮我们做好,因为 Vue 是响应式的。

我们不必每次更改 data 都调用setState,只需更改data即可! 只要要更新具有响应式的属性(props,computed 及 data 中的任何值),Vue 就会知道它何时发生变化。

回到计数器应用程序,我们仔细看看这里面的方法

methods: {
  increment() {
    this.count += 1;
  },
  decrement() {
    this.count -= 1;
  }
}

我们所要做的就是更新count,Vue 会检测到这个变化,然后用新值重新渲染我们的应用程序

Vue 的响应系统有很多细微的差别,如果你想要高效地使用Vue,理解它是非常重要的。如果你想更深入地了解Vue的响应系统,这里有更多要了解的东西。


避免命名冲突

Vue所做的另一件事是,使开发工作变得更好一点。

我们在组件上定义一些 props 和 data

export default {
  props: ['propA', 'propB'],
  data() {
    return {
      dataA: 'hello',
      dataB: 'world',
    };
  },
};

如果要在方法内部访问它们,则不必使用this.props.propA或this.data.dataA。 Vue 让我们完全省略了 props 和 dasta,只剩下了更整洁的代码。

我们可以使用this.propA或this.dataA访问它们:

methods: {
  coolMethod() {
    // Access a prop
    console.log(this.propA);

    // Access our data
    console.log(this.dataA);
  }
}

因此,如果我们不小心在data和 props中使用相同的名称,则会遇到问题。

如果发生这种情况,Vue 会给你一个警告,因为它不知道你想访问哪个。

export default {
  props: ['secret'],
  data() {
    return {
      secret: '1234',
    };
  },
  methods: {
    printSecret() {
      // 我们想要哪一个?
      console.log(this.secret);
    }
  }
};

当我们同时使用props和data时,Vue 的神奇之处就产生了。


props 和 data 一起使用

既然我们已经看到了 props 和 data 的不同之处,让我们来看看为什么我们需要两个,通过建立一个基本的应用程序。

我们将使用名为ContactInfo的组件显示此信息:

// ContactInfo
<template>
  <div class="container">
    <div class="row">
      Email: {{ emailAddress }}
      Twitter: {{ twitterHandle }}
      Instagram: {{ instagram }}
    </div>
  </div>
</template>
-------------------------------------
export default {
  name: 'ContactInfo',
  props: ['emailAddress', 'twitterHandle', 'instagram'],
};

ContactInfo组件接受 props:emailAddress,twitterHandle和instagram,并将其显示在页面上。

我们的个人资料页面组件ProfilePage如下所示:

// ProfilePage
<template>
  <div class="profile-page">
    <div class="avatar">
      <img src="user.profilePicture" />
      {{ user.name }}
    </div>
  </div>
</template>
-------------------------------------------------
export default {
  name: 'ProfilePage',
  data() {
    return {
      // In a real app we would get this data from a server
      user: {
        name: 'John Smith',
        profilePicture: './profile-pic.jpg',
        emailAddress: 'john@smith.com',
        twitterHandle: 'johnsmith',
        instagram: 'johnsmith345',
      },
    }
  }
};

我们的ProfilePage组件目前显示用户的配置文件图片及其名称,它还有用户数据对象。

我们如何从父组件(ProfilePage)向下获取数据到子组件(ContactInfo)

我们必须使用 props 传递数据。

首先,我们需要将ContactInfo组件导入ProfilePage组件

// Import the component
import ContactInfo from './ContactInfo.vue';

export default {
  name: 'ProfilePage',

  // Add it as a dependency
  components: {
    ContactInfo,
  },

  data() {
    return {
      user: {
        name: 'John Smith',
        profilePicture: './profile-pic.jpg',
        emailAddress: 'john@smith.com',
        twitterHandle: 'johnsmith',
        instagram: 'johnsmith345',
      },
    }
  }
};

其次,我们必须在<template>中添加组件:

// ProfilePage
<template>
  <div class="profile-page">
    <div class="avatar">
      <img src="user.profilePicture" />
      {{ user.name }}
    </div>

    <!-- Add component in with props -->
    <contact-info
      :email-address="emailAddress"
      :twitter-handle="twitterHandle"
      :instagram="instagram"
    />

  </div>
</template>

现在ContactInfo需要的所有用户数据都将沿着组件树向下流动,并从ProfilePage进入ContactInfo。

我们将数据保存在ProfilePage而不是ContactInfo中的原因是ProfilePage页面的其他部分需要访问user对象。

由于数据只向下流,这意味着我们必须将数据放在组件树中足够高的位置,以便它可以向下流到需要去的所有位置。

作者:Michael Thiessen
译者:前端小智
来源:medium  

链接: https://www.fly63.com/article/detial/8020

TypeScript中的React Render Props

和之前的文章一样,本文也要求你对render props有一些知识背景,如果没有官方文档可能会对你有很大的帮助。本文将会使用函数作为children的render props模式以及结合React的context API来作为例子。

Node.js之react.js组件-Props应用

render props是指一种在 React 组件之间使用一个值为函数的 prop 共享代码(个人理解:将组件进行函数化,通过调用组件名实现,组件的利用,以元素的形式调用,并渲染画面),具有 render prop 的组件接受一个函数

React组件设计模式-Render-props

写业务时,我们经常需要抽象一些使用频率较高的逻辑,但是除了高阶组件可以抽象逻辑,RenderProps也是一种比较好的方法。RenderProps,顾名思义就是将组件的props渲染出来。实际上是让组件的props接收函数,由函数来渲染内容。将通用的逻辑

props、属性、事件传递

之前看了一篇关于Vue开发技巧的文章,其中提到了在写高级组件时,通过v-bind=$props将props一次性向下传递。这种向下传递的方式我之前没有用过,便看了下官网的介绍,并补充了一些相关API用法,在这里记录一下,方便自己以后查看

props,挂载函数和快照测试

我们测试了通过一些 props 的结果。但是实际上,我们可以直接测试 props。让我们回到上次的 ToDoList组件,不过这次要用一个新的 Task 组件。我们将要测试 ToDoList 组件是否渲染 Task 组件,并将任务名称传递给他们。

vue props传值常见问题

传入的值想作为局部变量来使用,直接使用会 报错。错误是说的避免直接修改父组件传入的值,因为会改变父组件的值,解决方案:可以在data中重新定义一个变量,改变指向,但是也只是针对简单数据类型

React组件的state和props

React 的数据是自顶向下单向流动的,即从父组件到子组件中,组件的数据存储在 props 和 state 中。实际上在任何应用中,数据都是必不可少的,我们需要直接的改变页面上一块的区域来使得视图的刷新

验证 Vue Props 类型,这几种方式你可能还没试用过!

vue 要求任何传递给组件的数据,都要声明为 props。此外,它还提供了一个强大的内置机制来验证这些数据。这就像组件和消费者之间的契约一样,确保组件按预期使用。

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!