VueJS 之组件间的数据传递(props)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录

参考

项目描述
VueJS 官方文档Props
Vue.js 前端开发 快速入门与专业应用陈陆扬
搜索引擎Bing
哔哩哔哩黑马程序员

描述

项目描述
Edge109.0.1518.70 (正式版本) (64 位)
操作系统Windows 10 专业版
@vue/cli5.0.8
npm8.19.3
VueJS2.6.14

props

组件实例的作用域是孤立的。也就是说子组件的是无法直接获取到父组件中的数据的。VueJS 为组件开发提供了 props通过 props 父组件中的数据将能够传递给子组件而子组件则需要提前对 props 进行声明以便接收父组件传递过来的数据。
在对通用组件进行封装时合理地使用 props 能够提升组件的复用性。

举个栗子

父组件 App.vue

<template>
  <div class="container">
    <Child init="1"></Child>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 300px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

子组件 Child.vue

<template>
    <div class="container">
          <h3>Number: {{ init }}</h3>
    </div>
</template>

<script>
export default {
    props: ['init']
}
</script>

<style>
h3{
    color: #fff;
}
</style>

效果

效果

我们可以在使用组件时通过使用在子组件中使用 props 定义的属性来向子组件传递数据。

<Child init="1"></Child>

细节

驼峰式命名

排斥现象

HTML不区分大小写的。如果在一个 HTML 元素中存在多个同名属性仅存在大小写区别那么仅有在多个同名属性中第一个出现的属性会生效。

举个栗子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div CLass="zzh" styLe="background-color: dodgerblue; width: 100px; height: 100px" style="background-color: pink; width: 100px; height: 100px"></div>    
</body>
</html>

效果

效果

多管齐下

在 VueJS 中通过 props 定义的属性并不会出现 排斥现象同名属性均会生效。

父组件 App.vue

<template>
  <div class="container">
    <!-- 为三个自定义属性赋值以向子组件传递数据 -->
    <Child redheart="redheart" RedHeart="RedHeart" redHeart="redHeart"></Child>
    <div class="controller">
    </div>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 300px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

子组件 Child.vue

<template>
    <div class="container">
          <h3>redheart: {{ redheart }}</h3>
          <h3>RedHeart: {{ RedHeart }}</h3>
          <h3>redHeart: {{ redHeart }}</h3>
    </div>
</template>

<script>
export default {
    // 定义三个仅存在大小写区别的属性
    props: ['redheart', 'RedHeart', 'redHeart']
}
</script>

<style>
h3{
    color: #fff;
}
</style>

效果

效果

小驼峰式属性的另一种写法

如果使用 props 定义的属性是小驼峰式命名的那么你可以这样来进行数据的传递。

父组件 App.vue

<template>
  <div class="container">
    <!-- 为三个自定义属性赋值以向子组件传递数据 -->
    <Child red-heart="WIN"></Child>
    <div class="controller">
    </div>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 300px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

效果

效果

传递数值

验证

在向子组件传递数据时若直接使用 props 中定义的属性来传递数据传递的数值将为字符串类型。

父组件 App.vue

<template>
  <div class="container">
    <Child init="1"></Child>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 150px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

子组件 Child.vue

<template>
    <div class="container">
        <h3>Number: {{ init }}</h3>
        <div class="controller">
            <button class="add" @click="init += 1">Add</button>
            <button class="reduce" @click="init -= 1">Reduce</button>
        </div>
    </div>
</template>

<script>
export default {
    // 定义三个仅存在大小写区别的属性
    props: ['init']
}
</script>

<style>
h3{
    color: #fff;
    margin-top: 20px;
    margin-bottom: 10px;
}

.controller{
  width: 300px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.controller .add{
  width: 120px;
  height: 40px;
  background-color: #f40;
  /* 去除按钮元素携带的默认边框 */
  border: none;
  border-radius: 3px;
  color: rgb(250, 250, 250);
  font-size: 16px;
  font-weight: 600;
  margin-right: 60px;
  /* 设置鼠标悬停在按钮上时鼠标的样式 */
  cursor: pointer;
}

.controller .reduce{
  width: 120px;
  height: 40px;
  background-color: mediumorchid;
  border: none;
  border-radius: 3px;
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
}
</style>

效果

使用到的浏览器插件为 Vue.js devtools

效果

在最初由于父组件传递的数值为字符串类型在点击 Add 按钮后发生了字符串的拼接。在点击 Reduce 后发生了 隐式类型转换字符串数据类型转换为了数值类型因此在点击 Reduce 按钮后再点击 Add 按钮将发生数值的相加。

传递数值

如果你希望父组件向子组件传递数值那么你可以使用属性绑定指令指令作用的属性的值中的内容将作为 JavaScript 代码解析。

要在父组件中直接向子组件传递数值你仅需要将上一个示例中的

<Child init="1"></Child>

替换为

<Child v-bind:init="1"></Child>

在使用属性绑定指令后如果你希望传递字符串那么你可以

<Child v-bind:init="'1'"></Child>

因为指令作用的属性的值将作为 JavaScript 代码所以我们可以再添加一组引号该引号需要与外层引号不同类型来传递字符串类型的数据。

只读

警告

通过 props 定义的属性从父组件传递数据到子组件后数据仅建议子组件读取不建议子组件对其进行修改否则 VueJS 将在控制台中展示警告信息。

警告信息
可以看到在对按钮进行点击以改变自定义属性的值后控制台中都将展示警告信息。

优化

我们可以将接收到的数据保存到变量中通过点击按钮来改变变量中存储的值就可以避免更改自定义属性了。

父组件 App.vue

<template>
  <div class="container">
    <Child v-bind:init="1"></Child>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 150px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

子组件 Child.vue

<template>
    <div class="container">
        <h3>Number: {{ num }}</h3>
        <div class="controller">
            <button class="add" @click="num += 1">Add</button>
            <button class="reduce" @click="num -= 1">Reduce</button>
        </div>
    </div>
</template>

<script>
export default {
    // 定义三个仅存在大小写区别的属性
    props: ['init'],
    // 定义变量
    data() {
        return {
            num: this.init
        }
    }
}
</script>

<style>
h3{
    color: #fff;
    margin-top: 20px;
    margin-bottom: 10px;
}

.controller{
  width: 300px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.controller .add{
  width: 120px;
  height: 40px;
  background-color: #f40;
  /* 去除按钮元素携带的默认边框 */
  border: none;
  border-radius: 3px;
  color: rgb(250, 250, 250);
  font-size: 16px;
  font-weight: 600;
  margin-right: 60px;
  /* 设置鼠标悬停在按钮上时鼠标的样式 */
  cursor: pointer;
}

.controller .reduce{
  width: 120px;
  height: 40px;
  background-color: mediumorchid;
  border: none;
  border-radius: 3px;
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
}
</style>

效果

效果

配置

如果你使用对象作为为 export default{} 中的节点 props 的值那么你将可以对自定义属性拥有更多的控制权。

默认值

你可以为自定义属性添加默认值在父组件没有通过自定义属性传递数据时使用预先设定的数据。

父组件 App.vue

<template>
  <div class="container">
    <!-- 不为自定义属性传递数据 -->
    <Child></Child>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 150px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

子组件 Child.vue

<template>
    <div class="container">
        <h3>Number: {{ num }}</h3>
        <div class="controller">
            <button class="add" @click="num += 1">Add</button>
            <button class="reduce" @click="num -= 1">Reduce</button>
        </div>
    </div>
</template>

<script>
export default {
    // 定义三个仅存在大小写区别的属性
    props: {
        init: {
            // 设定当前自定义属性的默认值为 0
            default: 0
        }
    },
    // 定义变量
    data() {
        return {
            num: this.init
        }
    }
}
</script>

<style>
h3{
    color: #fff;
    margin-top: 20px;
    margin-bottom: 10px;
}

.controller{
  width: 300px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.controller .add{
  width: 120px;
  height: 40px;
  background-color: #f40;
  /* 去除按钮元素携带的默认边框 */
  border: none;
  border-radius: 3px;
  color: rgb(250, 250, 250);
  font-size: 16px;
  font-weight: 600;
  margin-right: 60px;
  /* 设置鼠标悬停在按钮上时鼠标的样式 */
  cursor: pointer;
}

.controller .reduce{
  width: 120px;
  height: 40px;
  background-color: mediumorchid;
  border: none;
  border-radius: 3px;
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
}
</style>

效果

效果

必填项

你可以通过设置 required 属性的值为 true 来规定父组件必须传递数据给子组件否则将抛出警告。

警告信息

required 属性设置为 true 后即使你设置了 default 属性来规定默认值如果父组件没有传递数据到子组件中控制台仍将抛出错误。

举个栗子

父组件 App.vue

<template>
  <div class="container">
    <!-- 不为自定义属性传递数据 -->
    <Child></Child>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 150px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

子组件 Child.vue

<template>
    <div class="container">
        <h3>Number: {{ num }}</h3>
        <div class="controller">
            <button class="add" @click="num += 1">Add</button>
            <button class="reduce" @click="num -= 1">Reduce</button>
        </div>
    </div>
</template>

<script>
export default {
    // 定义三个仅存在大小写区别的属性
    props: {
        init: {
            // 设定当前自定义属性的默认值为 0
            default: 0,
            // 规定父组件必须传递值给当前自定义属性
            required: true
        }
    },
    // 定义变量
    data() {
        return {
            num: this.init
        }
    }
}
</script>

<style>
h3{
    color: #fff;
    margin-top: 20px;
    margin-bottom: 10px;
}

.controller{
  width: 300px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.controller .add{
  width: 120px;
  height: 40px;
  background-color: #f40;
  /* 去除按钮元素携带的默认边框 */
  border: none;
  border-radius: 3px;
  color: rgb(250, 250, 250);
  font-size: 16px;
  font-weight: 600;
  margin-right: 60px;
  /* 设置鼠标悬停在按钮上时鼠标的样式 */
  cursor: pointer;
}

.controller .reduce{
  width: 120px;
  height: 40px;
  background-color: mediumorchid;
  border: none;
  border-radius: 3px;
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
}
</style>

效果
效果

数据类型

你可以通过设置 type 属性来规定父组件需要传递给子组件的数据的类型。如果父组件没有传递规定类型的数据或使用的默认值不为指定的数据类型VueJS 都将在控制台中抛出警告。

父组件 App.vue

<template>
  <div class="container">
    <!-- 不为自定义属性传递数据 -->
    <Child></Child>
  </div>
</template>

<script>
// 导入组件
import Child from '@/components/Child.vue';

export default {
  // 注册组件
  components: {
    Child
  }
}
</script>

<style>
/* 去除元素带有的部分默认样式 */
*{
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}

body{
  /* 使 body 元素中的内容居中显示 */
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container{
  width: 400px;
  height: 150px;
  background-color: dodgerblue;
  display: flex;
  /* 
  调整主轴方向为竖直方向列
  调整后该元素内部的元素将竖直排列。
   */
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* 设置圆角 */
  border-radius: 5px;
}
</style>

子组件 Child.vue

<template>
    <div class="container">
        <h3>Number: {{ num }}</h3>
        <div class="controller">
            <button class="add" @click="num += 1">Add</button>
            <button class="reduce" @click="num -= 1">Reduce</button>
        </div>
    </div>
</template>

<script>
export default {
    // 定义三个仅存在大小写区别的属性
    props: {
        init: {
            // 设定当前自定义属性的默认值为 0
            default: 0,
            // 规定当前自定义属性接收的数据的数据类型
            type: String
        }
    },
    // 定义变量
    data() {
        return {
            num: this.init
        }
    }
}
</script>

<style>
h3{
    color: #fff;
    margin-top: 20px;
    margin-bottom: 10px;
}

.controller{
  width: 300px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.controller .add{
  width: 120px;
  height: 40px;
  background-color: #f40;
  /* 去除按钮元素携带的默认边框 */
  border: none;
  border-radius: 3px;
  color: rgb(250, 250, 250);
  font-size: 16px;
  font-weight: 600;
  margin-right: 60px;
  /* 设置鼠标悬停在按钮上时鼠标的样式 */
  cursor: pointer;
}

.controller .reduce{
  width: 120px;
  height: 40px;
  background-color: mediumorchid;
  border: none;
  border-radius: 3px;
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
}
</style>

效果

效果

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue