介绍
Vue2中组件相关的内容 插槽 传值... 等等
# Vue2 组件的内容
- Vue的特性就是组件化十分的完善好用 通常可以设置传值
props
并且使用插槽slot
组件
- 组件需要设置
props
来接收父组件传递的值 并且props
可以设置默认值和类型 - 组件同过
this.$emi
给外部传值 - 组件可以设置具名插槽和默认插槽 推荐具名插槽
<slot name="" />
实现组件的高度自定义- 调用组件的页面 可以通过插槽 直接在组件中添加一些内容 十分的方便
<template>
<div>
<!-- 如果有值传入 -->
<template v-if="deptList">
<div v-for="(item,index) in deptList" :key="index" class="permission_check">
<div :class="['permission_check_box',PermissionChange === index ? 'backgroundTrue' : 'backgroundFalse']" @click="changePermission(index,item)">
<span class="textlimit">{{ item.name }}</span>
<!-- 插槽 右侧自定义内容 -->
<slot name="context" />
</div>
</div>
</template>
<!-- 如果没值传入 -->
<template v-else>
<div class="nullclass">暂无数据</div>
</template>
</div>
</template>
<script>
export default {
name: 'PermissionCheck',
props: {
// 接收渲染的数组
deptList: {
type: Array,
default: null
},
// 接收默认索引
defaultIndex: {
type: Number,
default: -1
},
},
data () {
return {
// 当前选中的索引
PermissionChange: this.defaultIndex
}
},
methods: {
// 修改事件
changePermission (index, item) {
// 判断是否选中同一个
if (this.PermissionChange === index) return
this.PermissionChange = index
// 传递修改的参数
this.$emit('item', item)
}
}
}
</script>
<style lang="scss" scoped>
.permission_check {
margin-bottom: -20px;
margin-top: 20px;
.permission_check_box {
height: 50px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding: 0px 20px;
cursor: pointer;
transition: $transition;
&:hover {
background: $boxHover;
}
}
.backgroundTrue {
background: $boxCheck;
}
.backgroundFalse {
background: #fff;
}
.textlimit {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
.nullclass {
color: #909399;
font-size: 12px;
text-align: center;
}
</style>
调用组件
- 调用组件并且传值 注意要导入组件哦
:
来给组件传递数值@
来接收组件用this.$emi
传来的数值 不需要写()
直接写methods
方法即可v-slot:
来使用组件的插槽
<template>
<div>
<permissioncheck :dept-list="deptList" @item="getItem">
<!-- 使用组件的插槽 -->
<template v-slot:context>
<div>123</div>
</template>
</permissioncheck>
</div>
</template>
<script>
// 注册选择栏
import permissioncheck from './components/permission-check'
export default {
components: {
permissioncheck
},
methods: {
// 获取组件传来的参数
getItem(e) {
console.log(e)
}
}
}
</script>
组件的效果
# 插槽进行传值
插槽分为 具名插槽 和默认插槽 我们不介绍默认插槽 以下内容为具名插槽的内容
我们在组件内设置插槽后 如何让插槽也能获取组件传来的值呢
组件设置插槽传值
- 和普通的传值一样 通过
:
进行传值
<template>
<slot name="context" :slotData="check" :slotIndxe="index" />
</template>
<script>
export default {
data () {
return {
// 插槽要传递的值
check: 123,
// 传递的第二个值
index: 1
}
},
}
</script>
模板中使用插槽传值
- 在父级作用域中(模板),我们可以使用带值的
v-slot
来定义我们提供的插槽 prop 的名字v-slot:插槽的名称="slotProps"
- 插槽传来的值 需要用
slotProps
进行接收 里面包含组件向插槽传递的值 (属性名为你在插槽中定义的名称)
<template>
<!-- slotProps就是接收组件向插槽传递的值 -->
<permissioncheck v-slot:context="slotProps">
<div>
<span @click="showMenu(slotProps.slotData ,slotProps.slotIndxe)" />
</div>
</permissioncheck>
</template>
<script>
export default {
methods: {
// 使用插槽传来的值
showMenu (data) {
console.log(data)
},
}
}
</script>
# 独占(唯一)插槽的简写
- 通常导入使用组件的插槽 我们需要
<template>
包住
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
- 如果我们只有唯一一个插槽 可以简写
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
- 当然 我们多个插槽的时候 还是需要用
<template>
包住 否则会报错
# 默认插槽
- xxxxxxxxxx # 进入你的项目目录cd mytest# 启动开发服务npm run servebash
创建一个 默认插槽的组件
<template>
<div class="outerBox">
<!-- 整个组件就一个插槽内容 -->
<slot />
</div>
</template>
<script>
export default {
name: 'Emptybox'
}
</script>
<style lang="scss" scoped></style>
Vue中使用
- 默认插槽直接
v-slot
使用即可
<template>
<!-- 默认插槽直接v-slot使用即可 -->
<emptybox v-slot>
123
</emptybox>
</template>
# 插槽的默认显示内容
- 可以在具名插槽的标签中设置默认显示 当不使用具名插槽的时候 显示默认内容
创建一个具名插槽 并设置默认显示内容
<template>
<div>
<slot name="context">{{ "当页面没有使用插槽的时候 我显示" }}</slot>
</div>
</template>
Vue中使用
<template>
<div>
<!-- 使用组件 显示组件插槽的默认内容 -->
<components />
<!-- 使用组件 并使用具名插槽代替其默认内容-->
<components>
<template v-slot:context="slotProps">
{{ '使用插槽并代替' }}
</template>
</components>
</div>
</template>
# 插槽使用标签中的内容
- 如果组件想实现使用标签之间的内容 比如
<components>用我用我</components>
那么需要在组件中 添加一个默认插槽<slot />
创建组件
- 在组件中 可以设置一个默认插槽
<slot />
来接收/使用标签中的内容
<template>
<div>
...组件自带的内容
<!-- 设置一个默认插槽 接收组件件标签中之间的内容 -->
<slot />
</div>
</template>
Vue中使用
- 在标签中之间 写我们的内容即可在组件的默认插槽中显示
<template>
<div>
<components>
<!-- 在组件标签中之间写内容 即可在组件的默认插槽中显示-->
我要使用标签之间的内容
</components>
</div>
</template>
# 父子传值修饰符.sync
- 父组件和子组件对相同的值进行修改 不需要使用
:
和@
我们可以二合一 用.sync
来代替 - 通常是用的的地方是 弹出层的显示与隐藏效果
父组件
- 假设我们
addass
组件的visible
值 父组件和子组件都需要修改 这时候我们给父组件添加.sync
<addass :visible.sync="visible" />
子组件
- 子组件通过
update:
来修改visible
值 实现.sync
的双向绑定
// props接收父组件传来的值
props: {
visible: {
type: Boolean,
default: false
}
},
// 通过update 实现.sync双向绑定
this.$emit('update:visible', false)
# Vue2和Vue3实现 v-model
- 在 Vue 2 中, 通过设置自定义组件的
v-model
(opens new window) 实现双向绑定 - 在 Vue 3 中,双向数据绑定的 API 已经标准化,以减少开发者在使用
v-model
指令时的混淆,并且更加灵活。
# Vue2中实现 v-model
- 对于
v-model
在组件上使用时, 就相当于绑定一个value prop
并触发input
事件 (默认行为) v-model
相当于一个语法糖, 是对绑定值和触发input
事件的简写:
父组件
<!--父组件引用子组件 -->
<ChildComponent v-model="propValue" />
子组件
// 封装子组件内部处理
// ChildComponent.vue
export default {
model: {
prop: 'smcsCode', // 默认是value prop是你传给父组件的值
event: 'check' // 默认是input event是你$emit设置的传递方法
},
props: {
smcsCode: {
type: [String, Number],
default: null
},
},
methods: {
// 修改SMCS
changeSmcs (e) {
// 向外暴露数据
this.$emit('check', e)
},
}
}
# Vue3中实现 v-model
- Vue3中
v-model
可以通过绑定多个属性的方式,向子组件传递多个值并且保证双向绑定 - 可以替代Vue2中
.sync
修饰符(.sync
修饰符在Vue3中已经被废弃)
父组件
<template>
<div>
<!-- v-model提供了一种双向绑定机制(在组件上-父子之间的数据交互) -->
<!-- .sync修饰符已经被废弃,替代方案是v-model -->
<TestEvent v-model:modelValue='info' v-model:msg='msg' />
</div>
</template>
<script>
import TestEvent from './TextEvent.vue'
import { ref } from 'vue'
export default {
name: 'App',
components: { TestEvent },
setup () {
const info = ref('hello')
const msg = ref('hi')
return { info, msg }
}
}
</script>
子组件
- Vue3中
v-model
可以使用多次
<template>
<div>
子组件 {{modelValue}}
</div>
<button @click='handleEdit'>点击</button>
</template>
<script>
export default {
name: 'TestEvent',
props: {
// Vue3中,v-model默认绑定的属性名称是modelValue
modelValue: {
type: String,
default: ''
},
msg: {
type: String,
default: ''
}
},
setup (props, context) {
const handleEdit = () => {
// 通知父组件修改数据 可以绑定多个v-model
// .sync修饰符:update:绑定的属性名称
context.emit('update:modelValue', 'nihao')
context.emit('update:msg', 'coniqiwa')
}
return { handleEdit }
}
}
</script>
# props 类型和默认参数
- props 单类型可以设置指定类型
type
和 默认值default
- props 多类型可以通过数组来设置 例如:
type: [Number,String]
默认值default
给任意一个类型的即可
type (规定数据类型)
String 字符串
Number 数字
Boolean 布尔
Array 数组
Object 对象
Date 日期
Function 函数
Symbol 独一无二的值(es6)
--------------------------------------------
default : (默认值)
基础数据类型: 直接赋值
数组对象渲染格式(Array): 用函数赋值 ()=>[]
默认值可以为 undefined 和 null
--------------------------------------------
required: (必填项)
默认为false,说明父级必须传入,否则会报错
--------------------------------------------
validator: 校验(验证传入的值是否符合规定)
设置一个方法 专门用来效验
validator: function(value){
return value>=0 && value<=100;
}
--------------------------------------------
// type多类型
type: [Number,String]
// default 给任意一个类型的值即可
default: 1
# 组件的注册使用
- 组件的使用分为 全局注册 和 局部注册
# 局部注册
- 每次使用的时候 需要
import
导入 并且需要在components
中进行注册 然后才能在template
Vue中使用
<template>
<div>
<!-- 使用局部组件 -->
<addass :visible.sync="visible" />
</div>
</template>
<script>
// 简简单单 导入个组件
import addass from './components/addass'
export default {
name: 'Assembly',
// components中注册一下
components: {
addass
},
}
</script>
# 全局注册
- 全局注册不需要每次导入 在全局入口文件
main.js
中导入 通过Vue.component('使用组件名称', 组件导入名称)
来进行全局注册 在template
中直接用即可
main.js 全局入口文件中注册
// 全局注册一个permissioncheck组件
import permissioncheck from './components/permission-check'
Vue.component('permissioncheck', permissioncheck)
在vue中调用
<template>
<div>
<!-- 使用全局组件 -->
<permissioncheck />
</div>
</template>
# 组件属性名自定义
- 有一种场景 当你封装了组件后 你不知道后端传来的渲染属性名是什么 这个时候 你不能修改组件的逻辑 你需要向组件传递一个自定义属性名
- 那我通常我们渲染是这样写的:
item.属性名
这种也是获取对象内值的一种方式 通过.
当遇到这种需要场景 就显得不足了 - 那么我们可以用 对象的另一种获取值的方式 通过
[]
也就是item[传来的属性名]
来看一下代码怎么写吧
- 封装组件的写法
- 我们组件通过props传值 告诉这个属性名叫什么即可
<template>
<div v-for="(item,index) in dataLeft" :key="index">
<template slot="title">
<!-- 我们通过[]方式 自定义设置对象的属性名 -->
<span class="textPass">{{ item[itemName] }}</span>
</template>
</div>
</template>
<script>
export default {
name: 'SelectMenu',
props: {
// 传入自定义对象的属性名
itemName: {
type: String,
default: 'name'
},
// 需要渲染的数组
dataLeft: {
type: Array,
default: undefined
},
},
data () {
return {
}
},
created () {
},
methods: {
}
}
</script>
- 使用组件 传递自定义属性名
- 我们通过
:
传值 来告诉组件指定的属性名即可
- 我们通过
<!-- 传入指定的属性名 -->
<selectMenu :item-name="'name'" :data-left="dataLeft" />