笔记内容:学习在 Vue 的单文件组件中如何管理数据。
目录:
众所周知,Vue是一个响应式的前端组件框架。响应式即是当业务逻辑中的数据发生改变的时候视图中的内容也会跟着改变。
<script> export default { data(){ return{ classmates:[ {id: 1, name: "可颂"}, {id: 2, name: "小许"}, {id: 3, name: "柯柯"}, ] }; }, render(){ return( <div class="hello"> { this.classmates.map((p, index) => ( <div key={p.id}> {`${index}.${p.name}`} </div> ))} </div> ); } } </script>
如上,data 函数返回了一个包含 classmates 数组的对象,当在创建一个 vue 的时候会将 data 函数返回的对象中的所有属性都加入到响应式系统中。
Q:data 为什么是函数?
A:只有返回一个生产 data 的函数,这个组件产生的每一个实例才能维持一份被返回对象的独立的拷贝。JS 中的对象都是通过引用关联的,如果使用的是同一个对象,那么可能会引用到同一个对象,数据可能就会发生紊乱。( Vue官网的解释:https://cn.vuejs.org/v2/guide/components.html#data-%E5%BF%85%E9%A1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0 )
Prop 是约定了从父组件向子组件传参的一个接口,可以通过 Prop 从父组件向子组件传递参数。
例子:
实现通过 Prop 从父组件 App.vue 传递参数给子组件 PropChild.vue
父组件 App.vue :
注册、引入、使用子组件 PropChild.vue。在模板上使用子组件 PropChild 时,传递参数给子组件的 parentName。
<template> <div> <prop-child parent-name="2"></prop-child> </div> </template> <script> import PropChild from "./components/PropChild"; export default { components:{ PropChild } } </script>
子组件 PropChild.vue:
子组件声明了一个 props,这个 props 是 parentName,然后模板插值打印出来 parentName(得到父组件通过prop传递过来的参数后)。
<template> <div> father {{ parentName }} </div> </template> <script> export default { props: ["parentName"] }; </script>
页面表现:
成功渲染输出 2
说明:
在父组件 App.vue 里引入、注册、使用子组件 PropChild。在子组件 PropChild.vue 里声明 props parentName,渲染 parentName。在父组件 App.vue 中使用 parentName,命名方式为烤肉串式命名即 parent-name,在父组件向子组件传递参数 2 (语句:<prop-child parent-name="2"></prop-child>)。
注意:
通过 props 从父组件向子组件传递了参数后,如果想要在子组件修改 props ,有人可能会尝试通过生命周期的钩子 mounted 改,但是这会报错,因为 Vue 从 Vue2 开始是单向数据流的。
从前面的例子可以知道,在 Vue2 里面父组件 props 的更新会流到子组件,但是反过来不行,这样子做的目的主要是防止子组件意外地改变父组件的状态从而导致应用数据难以理解,为什么这样说呢?因为 JS 中的对象是通过引入传入的,在对于一个数组或者对象类型的 props 来说,在子组件中去改变数组或者对象本身将影响到父组件之间的状态,如果组件层级比较多的时候,或者说这个数据被多个组件共享的时候,我们很难琢磨到组件是被哪里修改的。
Vue 官网中 Prop 验证的部分:https://cn.vuejs.org/v2/guide/components-props.html#Prop-%E9%AA%8C%E8%AF%81
例子
父组件 App.vue :
<template> <div> <prop-child parent-name="nana"></prop-child> </div> </template> <script> import PropChild from "./components/PropChild"; export default { components:{ PropChild } } </script>
子组件 PropChild.vue :
<template> <div> father {{ parentName }} </div> </template> <script> export default { props: { parentName: { // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) type: String, // 必填的字符串 required: true, // 带有默认值的字符串 default: "nana", // 自定义验证函数 validator(value){ // 这个值必须匹配下列字符串中的一个 const nameEnums = ["nana", "mona"]; return nameEnums.indexOf(value) !== -1; } } } }; </script>
页面表现:
父组件传入的参数是 “nana”,通过Prop验证,控制台没有报错。
如果将 App.vue 代码第 3 行传入的参数改为 “nana” 或 “mona” 以外的值,Prop验证将不通过,控制台会报错。
计算属性和侦听器的笔记:https://www.cnblogs.com/xiaoxuStudy/p/13230664.html
数组操作的笔记:https://www.cnblogs.com/xiaoxuStudy/p/13230631.html