Vue组件单向数据流

Vue
331
0
0
2022-04-06

如果组件 中 data 里的数据是固定的,那么页面上显示的时候内容就是一样的,而实际开发中,复用的组件里显示的内容往往是不同的,这就需要从父组件中传递不同的内容给子组件。

一、prop的使用方法

<template>
  <div id="app">
    <!-- 用 v-for 渲染文章列表 -->
    <!-- 父组件传article给子组件 -->
    <Article v-for="item in articleList" :key="item.title" :article='item'></Article>
  </div>
</template>

<script>
// 引入组件
import Article from '@/components/Article.vue';

export default {
  name: 'app',
  // 注册组件
  components: {
    Article
  },
  data: function() {
    return {
      articleList: [
        {
          cover: require('@/assets/images/article-cover-1.jpg'),
          title: '这张口罩图,根本不是网传的那么回事!',
          time: '2020-02-03 16:35:00',
          likes: 9657,
          content: '1日晚,一张宣称“官员领导戴的都是N95口罩,医护人员戴的却都是一次性口罩”的贴文在网络上疯传,有人还给这张图起名为“权力PK天使”。不过,耿直哥核实后发现,这个贴文中所叙述的内容并不属实。下图,便是1日晚起在微博等平台上疯狂传播的那张宣称“领导戴的都是N95口罩,医生佩戴的都是一次性”口罩的贴文。'
        },
        {
          cover: require('@/assets/images/article-cover-2.jpg'),
          title: '火神山是怎样筑成的?',
          time: '2020-02-04 18:33:00',
          likes: 898,
          content: '建一座医院要多久?一个问题:建造一座1000床位的医院需要多久?在中国湖北,武汉,从一块平地上建造火神山医院,1000个床位,具备新风系统、负压系统、急救室、污水处理、食堂、水电气网,并容纳2000医护人员的住宿,需要10天。'
        }
      ]
    }
  }
}
</script>

<style lang="scss">
#app {
  width: 100%;
  height: 100%;
}
</style>

上面代码中,父组件以:article的形式传值给子组件。

子组件中用prop接收父组件传的值:

<template>
  <div class="article">
    <div class="article-cover">
      <img :src="article.cover" alt="">
    </div>
    <div class="info">
      <!-- 文章标题 -->
      <div class="article-title">{{ article.title }}</div>
      <!-- 文章时间 -->
      <div class="article-time">{{ formatTime }}</div>
      <!-- 文章点赞人数 -->
      <div class="article-likes">{{ article.likes }}</div>
      <!-- 文章简介 -->
      <div class="article-content">{{ brief }}</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Article',
  // 接收父组件传来的数据,要求写明数据类型
  props: {
    article: Object
  },
  // 计算属性
  computed: {
    // 对时间进行格式化,以 2020-01-30 01:00:00 为例,格式后为“2020年1月30日 1时0分”
    formatTime: function() {
      // ??
      if(this.article){
        const dt = new Date(this.article.time);
        const year = dt.getFullYear();
        const month = dt.getMonth();
        const date = dt.getDate();
        const hours = dt.getHours();
        const minutes = dt.getMinutes();
        const seconds = dt.getSeconds();
      }
       return `${year}${month}${date} ${hours}${minutes}分`;
    },
    // 截取文章内容的前 35 个字,并加上省略号,形成文章简介
    brief: function() {
      return this.article && (this.article.content.substr(0,35) + '...') || ''
    }
  }
}
</script>

<style lang="scss" scoped>
.article {
  width: 400px;
  display: flex;
  padding: 10px 0;
  border-bottom: 1px solid #dbdbdb;
  &:last-child {
    border: none;
  }
  .article-title {
    font-size: 16px;
    font-weight: 500;
    color: #42b983;
    text-align: justify;
  }
  .article-cover {
    flex: none;
    width: 120px;
    margin-right: 10px;
    > img {
      width: 100%;
    }
  }
  .article-content, .article-time, .article-likes {
    font-size: 14px;
  }
  .article-time, .article-likes {
    margin: 10px 0;
    color: #c5c5c5;
  }
}
</style>

二、单向数据流

单向数据流指的是父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样可以防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

简单来说:

1、prop 可以实现父到子的数据传递;

2、父组件中的数据变化,会通过 prop 传递到子组件;

3、子组件不能直接修改父组件通过 prop 传递过来的数据;


Vue组件单向数据流


但实际开发中常会遇到传到子组件中的数据需要处理后才能使用的情况,比如排序、格式化等,这时候怎么办呢?

三、prop传入数据的处理

1. prop 传入的数据需要处理

在上面第二段代码中,用计算属性来对传入的数据进行处理

2. prop 传入的数据作为本地数据使用

如果想将 prop 传递的初始值作为一个本地数据使用,可以定义一个本地的 data 属性并将这个 prop 用作其初始值:

props: ['initialTitle'],
data: function () {
  return {
    // 要读取 prop 里的 initialTitle,要在前面加 “this.”
    // 将传入的 initialTitle 作为本地属性 title 的初始值
    title: this.initialTitle
  }
}