vue protype(【Vue2】组件通信 之 props)
Props 声明
props 可以是 string[] / Object 的形式 sreing[] 写法 <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> 对象式写法(推荐) <template> <div> <!-- 设置自定义属性 (传递数据) --> <Son name="superman" :age="21" /> <!-- 注意, 这里使用 v-bind 绑定 age, 所以传递的是数值 --> </div> </template> <script> export default { name: Son, // 配置 props 属性 (接收数据) props: { name: String, // 限制 name 的属性值为 string 类型 age: Number, // 限制 age 的属性值为 number 类型 }, }; </script>传递 prop 的细节
可以在父组件中给子组件标签元素设置自定义属性 :prop-name="XXX" / :propName="XXX" 传递数据
即可在子组件中通过 props: ["propName"] 接收数据 可以使用一个对象绑定多个 prop // 假设有一个 post 对象 const post = { id: 1, title: My Journey with Vue, }; <!-- 以下两种写法等效: --> <BlogPost v-bind="post" /> <BlogPost :id="post.id" :title="post.title" />单向数据流
每次父组件更新后 ,所有的子组件中的 props 都会被更新到最新值 因此 ,我们不可以在子组件中修改 props 传递过来的数据 。否则: 控制台会发出警告(子组件中显示的数据还是会改变 一旦父组件的数据更新,子组件接收的对应数据也会被更新 <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 ,在页面完成时被调用一次;子组件修改数据后 ,重新渲染子组件 ,被调用一次此时我们再在父组件中修改原数据 ,则子组件的数据也会被修改 ,就是说 ,子组件之前修改的数据会被覆盖
参与页面数据显示的方法 showApp 、showSon ,在页面完成时依次被调用一次;父组件修改数据后 ,页面重新渲染 ,再依次被调用一次如果非得在子组件中获取并修改父组件传递的数据,我们可以将 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>可以发现 ,页面初始化时 ,showApp 、showSon 依次被调用
不论在子组件还是在父组件中修改数据 ,都能成功修改数据 、并重新渲染子组件模版 ,showSon 被调用子组件传递数据给父组件
父组件给子组件传递函数,子组件给函数传入参数 ,从而实现子组件给父组件传递数据
通过自定义属性 ,父组件给子组件传递函数 子组件通过 props 属性接收该函数 在调用该函数时,传入数据作为参数 父组件就能 [以参数的形式] 接收到子组件传递过来的数据 <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>Prop 校验
{ // 基础类型检查 propA: Number, // 给出 `null` 和 `undefined` 值则会跳过任何类型检查 // 多种可能的类型 propB: [String, Number], // 必传, 且为 String 类型 propC: { type: String, required: true }, // Number 类型的默认值 propD: { type: Number, default: 100 }, // 对象类型的默认值 propE: { type: Object, // [对象] / [数组] 的默认值, 必须从一个工厂函数返回 // 该函数接收组件所接收到的原始 prop 作为参数 default(rawProps) { return { message: hello } } }, // 自定义类型校验函数 propF: { validator(value) { // The value must match one of these strings // return false 则抛出警告 (开发模式下) return [success, warning, danger].includes(value) } }, // 函数类型的默认值 propG: { type: Function, // 不像对象或数组的默认, 这不是一个工厂函数. 这会是一个用来作为默认值的函数 default() { return Default function} } } 一些个细节 所有 prop 默认都是可选的 ,除非声明了 required: true 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined;Boolean 类型的未传递 prop 将被转换为 false
这可以通过为它设置 default 来更改 —— eg:设置为 default: undefined 将与非布尔类型的 prop 的行为保持一致 如果声明了 default 值 ,那么在 prop 的值被解析为 undefined 时 ,无论 prop 是未被传递还是显式指明的 undefined ,都会改为 default 值 prop 的类型 可以传递以下类型的数据:① String 、② Number 、③ Boolean、④ Symbol 、⑤ Date 、 ⑥ Array、⑦ Object 、⑧ Function 另外 ,type 也可以是自定义的类或构造函数 ,Vue 将会通过 instanceof 来检查类型是否匹配 // 假设有 Person 类 class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } } defineProps({ author: Person, // 使用 Person 类约束类型 // Vue 会通过 instanceof Person 来校验 author prop 的值是否是 Person 类的一个实例 }); Boolean 类型转换 // 假设组件设置如下 props defineProps({ disabled: Boolean, }); <!-- 等同于传入 :disabled="true" --> <MyComponent disabled /> <!-- 等同于传入 :disabled="false" --> <MyComponent /> 当一个 prop 被声明为允许多种类型时 ,无论声明类型的顺序如何 ,Boolean 类型的特殊转换规则都会被应用 defineProps({ disabled: [Boolean, Number], });创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!