工程地址:
启动进入的是 home 页面,主要是以下几个模块:
本篇先学习下header部分的代码。
<head-top signin-up='home'>
<span slot='logo' class="head_logo" @click="reload">ele.me</span>
</head-top>
针对这段代码有两个知识点, prop 和 slot。分别详细学习下。
prop
学习资料
定义方式
// 字符串数组形式列出
props: ['title', 'likes']
// 指定值类型 & 默认值 & 验证要求,以对象形式列出
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
传递静态或动态
// 传递 数字,布尔,数组,对象都需要用 v-bind,用以和 string 区分。
// 传入一个对象的所有property,可以不用 v-bind
post: {
id: 1,
title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
单向数据流
父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
常见的两种子组件试图变更prop的情形和建议处理方式:
- prop传递初始值,子组件后续将其作为本地数据操作。
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter // 定义本地属性,然后prop作为初始值
}
}
- prop传递原始值,子组件基于此转换。
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
// 最好定义计算属性来解决
}
}
slot
学习资料
什么是插槽
官网的定义: 将 slot 元素作为承载分发内容的出口。 比较形象的理解:子组件定义了一个插座(slot), 父组件定义电器,即父向子传递。
v-slot 只能添加在 template 标签上。
后备内容(默认内容)
默认内容只会在没有提供内容的时候被渲染。
具名插槽 vs 匿名插槽
<!-- 子组件 -->
<header>
<!-- 具名插槽 -->
<slot name="header"></slot>
<!-- 具名插槽的缩写 -->
<template #header>
<h1>Here might be a page title</h1>
</template>
</header>
<main>
<!-- 匿名插槽,带有隐含的名字“default” -->
<slot></slot>
</main>
<!-- 父组件 -->
<template v-slot:header>
<!-- 传入header插槽 -->
<h1>Here might be a page title</h1>
</template>
<!-- 任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。 -->
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<!-- 和上面的实现一样,只是更明确一些 -->
<!-- 也可以直接v-slot 不带参数的 v-slot 被假定对应默认插槽 -->
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
作用域插槽
插槽作用域里写的: 父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。 那怎样让插槽内容能够访问子组件中才有的数据?
<!-- 子组件 current-user.vue -->
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
<!-- 父组件 -->
<current-user>
<!-- 绑定在slot元素上的attribute称为插槽prop -->
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>