IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【Vue】组件通信 之 props -> 正文阅读

[JavaScript知识库]【Vue】组件通信 之 props

父组件 → 子组件

  • 父组件中,给子组件标签元素设置自定义属性 attrKey="attrVal",[属性值 attrVal] 为需要传递的数据
    子组件中,给组件实例设置 props 属性,属性值包含父组件给子组件标签元素设置的自定义 [属性名 attrKey]
    实现:父组件给子组件传递数据
  • props 可以是 [数组式写法] / [对象式写法]
    [对象式写法] 允许高级配置,eg:类型检测、默认值、自定义验证…

数组式写法

props 的属性值为数组时,其元素为父组件给子组件标签元素设置的自定义 [属性名 attrKey]
注意:属性名 attrKey 不要用驼峰命名法,因为 html 代码不区分大小写

<template>
    <div>
        <!-- 设置自定义属性 (传递数据) -->
        <Son name="superman" age="21" />
    </div>
</template>

<script>
import Son from "./components/Son.vue";
export default {
    name: "App",
    components: { Son },
};
</script>
<template>
    <div>
        <h2>姓名: {{ name }}</h2>
        <h2>年龄: {{ age }}</h2>
    </div>
</template>

<script>
export default {
    name: "Son",
    // 配置 props 属性 (接收数据)
    props: ["name", "age"],
};
</script>
  • 可以传递各种数据类型:① String、② Number、③ Boolean、④ Symbol、⑤ Date、 ⑥ Array、⑦ Object、⑧ Function

对象式写法(推荐)

props 的属性值为对象时,该对象的属性名为父组件给子组件设置的自定义 [属性名 attrKey];属性值为配置对象
注意:属性名 attrKey 不要用驼峰命名法,因为 html 代码不区分大小写

① 修改父组件的模版:

<template>
    <div>
        <!-- 设置自定义属性 (传递数据) -->
        <Son name="superman" :age="21" />
        <!-- 注意,这里使用 v-bind 绑定 age,所以传递的是数值 -->
    </div>
</template>

② 修改子组件的脚本:

<script>
export default {
    name: "Son",
    // 配置 props 属性 (接收数据)
    props: {
        name: {
            type: String, // 限制数据的类型
            require: true, // 必须传值
        },
        age: {
            type: Number,
            default: 18, // 默认值
        },
    },
};
</script>
  • 如果只是限制数据的类型,可以简写:
    // 配置 props 属性 (接收数据)
    props: {
        name: String, // 限制数据的类型
        age: Number,
    },
  • 默认值为 [对象 Object] / [数组 Array] / [函数 Function] 时,必须通过工厂函数获取
  • 可以通过 validator 函数自定义限制条件

① 修改父组件模版:

<div>
    <!-- 注意这里没有设置 age 属性 -->
    <Son name="superman" />
</div>

② 修改子组件脚本:

props: {
    name: {
        type: String,
        require: true,
        // 自定义检测 - return false 则报错
        validator(val) {
            console.log("val", val); // val superman
            return val == "superman";
        },
    },
    age: {
        type: [Number, Object], // 限制为多个类型中的一种
        // 通过工厂函数设置默认值
        default() {
            return {
                realAge: 81,
                showAge: 18,
            };
        },
    },
},

渲染问题(单向数据流)

  • 父组件的数据更新时,子组件接收到的对应的数据也会被更新
  • 因此,我们可以在子组件中修改 props 传递过来的数据。否则:
    1. 控制台会发出警告(子组件中显示的数据还是会改变
    2. 一旦父组件的数据更新,子组件接收的对应数据也会被更新
  • 总之,父组件数据的更新会向下传递至子组件,但子组件不能更新父组件中的数据
<template>
    <div>
        <h1>{{ showApp() }}</h1>
        <button @click="num++">修改 age</button>
        <hr />
        <Son :age="num" />
    </div>
</template>

<script>
import Son from "./components/Son.vue";

export default {
    name: "App",
    components: { Son },
    data() {
        return { num: 21 };
    },
    methods: {
        showApp() {
            console.log("showApp");
            return "App";
        },
    },
};
</script>
<template>
    <div>
        <h2>{{ showSon() }}</h2>
        <h2>年龄: {{ age }}</h2>
        <button @click="age++">修改 age</button>
    </div>
</template>

<script>
export default {
    name: "Son",
    props: ["age"],
    methods: {
        showSon() {
            console.log("showSon");
            return "Son";
        },
    },
};
</script>

在子组件中 修改父组件传递过来的数据:控制台抛出警告、子组件的数据可以被成功修改、重新渲染子组件
参与子组件数据显示的方法 showSon,在页面完成时被调用一次;子组件修改数据后,重新渲染子组件,被调用一次

此时我们再在父组件中修改原数据,则子组件的数据也会被修改,就是说,子组件之前修改的数据会被覆盖
参与页面数据显示的方法 showAppshowSon,在页面完成时依次被调用一次;父组件修改数据后,页面重新渲染,再依次被调用一次

  • 如果非得在子组件中获取并修改父组件传递的数据,我们可以将 props 中的数据赋值到 data
    此时我们操作的,其实就是子组件自己的数据啦
<template>
    <div>
        <h2>{{ showSon() }}</h2>
        <h2>年龄: {{ sonAge }}</h2>
        <button @click="sonAge++">修改 sonAge</button>
    </div>
</template>

<script>
export default {
    name: "Son",
    data() {
        return { sonAge: this.age }; // 将接收到的数据设置为组件自己的数据
    },
    props: ["age"],
    methods: {
        showSon() {
            console.log("showSon");
            return "Son";
        },
    },
};
</script>

此时,子组件渲染的是 data 中的数据 sonAge
更新子组件 data 中的数据,子组件会被重新渲染、showSon 被调用
更新父组件的数据,父组件会被重新渲染、showApp 被调用;此时子组件不会被重新渲染

注意:自己的数据不要与接收的数据同名,否则会报错(页面会优先显示 props 的数据

引用类型数据

  • 因为是赋值处理,所以传递引用类型数据要特别注意,因为引用类型的数据操作的是地址
    此时,传递的是父组件的数据的引用;就是说,父子组件操作的是同一数据
<template>
    <div>
        <h1>{{ showApp() }}</h1>
        <button @click="sonObj.num++">修改 age</button>
        <hr />
        <!-- 传入对象数据 -->
        <Son :ageObj="sonObj" />
    </div>
</template>

<script>
import Son from "./components/Son.vue";

export default {
    name: "App",
    components: { Son },
    data() {
        return { sonObj: { num: 21 } };
    },
    methods: {
        showApp() {
            console.log("showApp");
            return "App";
        },
    },
};
</script>
<template>
    <div>
        <h2>{{ showSon() }}</h2>
        <h2>年龄: {{ ageObj.num }}</h2>
        <!-- 直接修改对象数据 -->
        <button @click="ageObj.num++">修改 ageObj</button>
    </div>
</template>

<script>
export default {
    name: "Son",
    props: ["ageObj"], // 接收对象数据
    methods: {
        showSon() {
            console.log("showSon");
            return "Son";
        },
    },
};
</script>

可以发现,页面初始化时,showAppshowSon 依次被调用
不论在子组件还是在父组件中修改数据,都能成功修改数据、并重新渲染组件模版,showSon 被调用

子组件 → 父组件

父组件给子组件传递函数,子组件给函数传入参数,从而实现子组件给父组件传递数据

  1. 通过自定义属性,父组件给子组件传递函数
  2. 子组件通过 props 属性接收该函数
  3. 在调用该函数时,传入数据作为参数
  4. 父组件就能 [以参数的形式] 接收到子组件传递过来的数据
<template>
    <div>
        <p>父组件数据:{{ msg }}</p>
        <hr />
        <!-- 给子组件绑定属性,传递方法 -->
        <Son :parentFun="parentFun" />
    </div>
</template>

<script>
import Son from "./components/Son.vue";
export default {
    name: "App",
    components: { Son },
    data() {
        return { msg: "father" };
    },
    methods: {
        parentFun(val) {
            console.log("val", val);
            this.msg += val;
        },
    },
};
</script>
<template>
    <div class="son">
        <!-- 调用方法,传入数据 -->
        <button @click="parentFun(sonMsg)">
            点击将子组件的数据传递给父组件
        </button>
    </div>
</template>

<script>
export default {
    name: "Son",
    props: ["parentFun"], // 设置 props 属性,接收方法
    data() {
        return { sonMsg: "son" };
    },
};
</script>



【Vue】组件通信 之 自定义事件



【Vue】组件通信 之 其他方法



  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 18:43:07  更:2022-07-20 18:45:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:02:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码