#完整原文地址见简书www.jianshu.com/p/1bc868ff4… #更多完整Vue笔记目录敬请见《前端 Web 笔记 汇总目录(Updating)》
#本文内容提要
Vue.createApp()的参数是页面的根组件自定义的子组件是可以被复用的,且多个复用子组件之间数据相互独立
自定义的【全局子组件】方便快捷,随处可用,但影响性能
定义局部组件
局部组件再例
局部组件语法一重点
全局组件、局部组件比较
父子组件间相互通信的方式
动态参数传参 解决 number转string的问题
传参类型校验
- 传参类型校验再例【Boolean例】
- 传参类型校验再例【Function例】【传递函数型参数】
props块
props块的required属性 配置必填效果props块的default属性 配置默认值props块的validator属性 配置参数值大小限制多个数据 传参时常规写法
使用Object方式优化
v-bind传参HTML中,推荐使用 横杠分割法 代替 驼峰命名法
单向数据流的理解
- 解决方法
- 单向数据流存在的意义
Non-prop 属性
- 子组件使用
inheritAttrs: false属性配置,可以拒绝继承接收 父组件传递过来的属性- Non-props 应用场景
$attrs修饰符- $attrs修饰符 再例
- $attrs 运用于生命周期方法中
####`Vue.createApp()`的参数是页面的根组件 **`Vue.createApp()`传入的参数,将作为页面的根组件, 似Android的`rootView`:** ``` Hello World! heheheheheheda ``` 效果:
####自定义的子组件是可以被复用的,且多个复用子组件之间数据相互独立 **如下复用三个``自定义子组件,三个``之间数据相互独立:** ``` ``` 效果:
####自定义的【全局子组件】方便快捷,随处可用,但影响性能 **自定义的全局子组件方便快捷,随处可用, 任何地方都可以引用子组件,如下【似Android的Fragment】代码;
但只要使用`.component()`定义了子组件,子组件便挂载在`VueApp`实例上了, 即使不调用该子组件,它也会占用内存和性能:** ``` ``` 效果:
####定义局部组件 语法: ``` const 局部组件实例名= { data() { return { ... } }, template: ... }
const app = Vue.createApp({
components: { 定义局部组件引用名 : 局部组件实例名},
template: <div> <局部组件引用名/> </div>
});
案例代码:
**效果:**
<br>
**如果`局部组件实例名` 与 `定义的局部组件引用名` 相同,
则可以直接使用以下的`简写语法`:**
效果:
<br>
####局部组件再例
效果:
<br>
####局部组件语法一重点
**为了将`局部组件`的`实例名` 同 普通的js(驼峰命名法)变量区分开来,
推荐使用`首字母大写`的`驼峰` 对 `局部组件`的`实例名`进行命名,
同时,
Vue代码在`template`中引用`局部组件时`时,
会忽略大小写和杠号 对`components`中定义的组件进行映射;
如下,
`<counter />`忽略了大小写 映射到 `Counter`;
`<heheda-dom />`忽略了横杆号和大小写 映射到 `HehedaDom`:**
效果:
<br>
####全局组件、局部组件比较
>**全局组件定以后,随处可用,方便快捷,任何地方都可以引用子组件,
但性能不高(定以后 不用时也 挂载并占用内存),
命名建议,小写字母 配合 横线隔开;<br>
局部组件 定义后 需注册才能使用才会占用资源,性能较高,
但使用较麻烦,
>命名建议,大写字母 配合 驼峰命名法;**
<br>
####父子组件间相互通信
**主要是借助`props`的方式:**
Hello World! heheheheheheda
```
效果:
####动态参数传参 解决 number转string的问题 静态传参,存在如题问题: ``` ``` 
将数据写在data版块中,借用v-bind 动态传参,解决以上问题:
<script>
const app = Vue.createApp({
data() {
return {
num : 666
}
},
template: `
<div><test :content = 'num'></div>`
});
app.component('test', {
props: ['content'],
template:`<div>{{content}}<br>
{{typeof content}}</div>`
})
const vm = app.mount('#heheApp');
</script>
####传参类型校验 >**传参类型校验支持:String、Boolean、Array、Object、Function、Symbol 等类型;**
关键:
将props位的值,从数组形式换为对象(键值)形式,
键为承接属性,值为期望值类型:
<script>
const app = Vue.createApp({
data() {
return {
num : 666
}
},
template: `
<div><test :content = 'num' /></div>`
});
app.component('test', {
props: {
content : String,
},
template:`<div>{{content}}<br>
{{typeof content}}</div>`
})
const vm = app.mount('#heheApp');
</script>
如上代码,期望得到一个String类型的参数,却传入一个number类型的参数,
则运行时 会刷出报错警告:
更正入参类型,则不再报错:
<script>
const app = Vue.createApp({
data() {
return {
num : "666"
}
},
template: `
<div><test :content = 'num' /></div>`
});
app.component('test', {
...
})
const vm = app.mount('#heheApp');
</script>
####传参类型校验再例【Boolean例】 ``` ``` 
####传参类型校验再例【Function例】【传递函数型参数】 ``` ```  **更正类型【传递函数型参数】:** ``` ``` 
####`props`块的`required`属性 配置`必填`效果 **`props`块的`required`属性配置`true`时,`要求`对应配置的属性`要传参数`, 没有传参数,则报错;
如下案例,配置了`required`属性为`true`,但没有传参:** ``` ``` 效果: **传了参就好起来了:** ``` ``` 
####`props`块的`default`属性 配置`默认值` **如果没有传入参数到子组件,则使用`default`属性 配置的`默认值`:
如下例, 配置默认值86868686886, 不传参数进去子组件:** ``` ``` 效果:
**当然使用`函数返回数据的形式【适用于返回值需要计算的场景】`也是可以的, 如下代码 可以达到同样的效果:** ``` ```
####`props`块的`validator`属性 配置`参数值大小限制` 如下,限制入参必须小于1000,否则报错: ``` ``` 效果: 将入参改为小于1000的数就好起来了: ``` ``` 效果:
####多个数据 传参时常规写法 ``` Hello World! heheheheheheda ``` 效果:
####使用Object方式优化`v-bind`传参 **``一行等价于 ``;** ``` ``` **此处代码实现的效果跟上面例子是一样的;**
####HTML中,推荐使用 横杠分割法 代替 驼峰命名法 **并且,props承接 横杠分割法字段 时候, 需用对应的 驼峰命名法 字段 去承接,否则无法承接到数据:** ``` ``` **props中 横杠分割法字段参数 无法承接到数据: 使用对应的 驼峰命名法 字段参数, 承接到 横杠分割法字段:** ``` ``` 
####单向数据流的理解 **指 父组件 可以向 子组件 传递数据, 但是 子组件 无法修改 父组件 传递过来的参数变量; 数据只能从 父组件 流向 子组件, 所谓 单向数据流;** ``` ``` 如上代码,运行之后点击组件,会报错提示无法更改值:
####解决方法 **子组件自身准备一个 data字段, 用于拷贝一份父组件传来的参数数据; 后面要借助数据做更新的时候, 使用这个拷贝数据即可:** ``` ``` 效果,可点击实现功能了:
####单向数据流存在的意义 >**如果子组件可以修改父组件的数据,会引发很多逻辑隐患; 如假设父组件 将一个数据 传给若干个子组件, 这时候如果 子组件 可以更改 父组件的字段, 那这时 每一个子组件 都同时对这个 数据 进行修改, 那父组件的数据字段 势必乱套【有点Java的线程安全的意思了】; 所以, 规定数据的单向性,可以避免很多设计逻辑问题 和隐患;**
####父子组件传参,静态传参,父组件中直接写`[属性:值]`,动态传参,则需借助`v-bind`,即`v-bind:属性 = 数据字段`;
####Non-prop 属性 指 **父组件 传数据给 子组件时,子组件 不通过`prop`属性 接收 的属性; 这时,无论传递是否有使用`v-bind`, `父组件`传递的这个`数据字段`,都会成为 `子组件`最外层组件的`属性`;** ``` Hello World! heheheheheheda ``` 
####子组件使用`inheritAttrs: false`属性配置,可以拒绝继承接收 父组件传递过来的属性 ``` ``` 
####Non-props 应用场景 **可以轻松传递样式:** ``` ``` 
####$attrs修饰符 >**在之前的笔记 —— [Vue3 | Vue中的诸多花样样式写法 以及 相关规则和技巧](https://www.jianshu.com/p/cdbd2670e075) 中的 【子组件样式 默认跟随 父组件】问题中已经有所提及这个方法了;
当子组件的`template`中有拥有“两个以上最外层组件”时, 父组件传递过来的`Non-props`会失效, 因为没有用`v-bind`指定的属性,只能传给一个`最外层组件`, 当有多个时就会失效;
**
被v-bind = $attrs修饰的DOM组件,
会接收父组件传递的所有non-props属性:
<script>
const app = Vue.createApp({
template: `
<div>
<counter style="color:blue;" msg="heheda" msg2="lueluelue" />
</div>`
});
app.component('counter', {
template:`
<div>Counter</div>
<div v-bind="$attrs">Counter</div>
<div>Counter</div>
`
})
const vm = app.mount('#heheApp');
</script>
####$attrs再例 >**注意: `v-bind="$attrs"`,`"$attrs"`是一个包含多个值的意义值, 惯例一梭子传给被配置的组件, 没有用`变量`承接,所以要使用`v-bind`承接,不可简写;
但是`:heheda="$attrs.msg"`中,"`$attrs.msg`"是一个`js`表达式,且仅代表一个值, 所以可以用`变量`承接,且可以简写"v-bind";** ``` ``` 效果:
####$attrs 运用于生命周期方法中 ``` ``` 