Vue
1、vue中@click.native的使用
组件中时常看到@click.native。在项目中遇到后,简单介绍下:
@click.native是给vue组件绑定原生事件
- 1、给vue组件绑定事件时候,必须加上native ,否则会认为监听的是来自Item组件自定义的事件
- 2、等同于在子组件中: 子组件内部处理click事件然后向外发送click事件:$emit("click".fn)
如果是组件绑定键盘事件:
如给el-input绑定回车触发事件 @keyup.enter.native=
给普通div绑定回车事件 @keyup.enter =""
2、.sync修饰符
我们常见的父与子组件之间的通信,一般都是父组件自定义属性,子组件通过子props接收,如果想修改父组件传递过来的变量,一般使用this.$emit(事件名,参数,…)的形式进行事件提交.sync是vue中用于实现简单的“双向绑定”的语法糖.
- .sync修饰符之前的写法
父组件:
<parent :myMessage=“bar” @update:myMessage=“func”>
func(val){
this.bar = val;
}
子组件中的事件触发函数:
func2(){
this.$emit(‘update:myMessage’,valc);
}
- 使用.sync修饰符的写法
会简化上面的写法,父组件不需要定义更新触发函数。
父组件:
<comp :myMessage.sync="bar"></comp>
子组件:
this.$emit('update:myMessage',valc);
3、el-table-column 使用 v-if 做动态列效果导致的顺序错乱处理
场景描述
点击不同的按钮之后,就会切换不同的table表格,这两个表格的列表字段是不同的
- 人工智能榜的表头
- 企业百强榜的表头
错误代码展示
使用饿了么的el-table表格,将相应的表头字段分为两组,使用v-if去控制是否展示
实际效果
点击企业百强榜后,表头的顺序错乱
- 正确的表头字段排序应该是 企业名称 => 企业详情 => 状态
解决方法
使用 v-if 后,可能与 vue 的渲染机制有关,导致排序混乱;每一个 el-table-column 都加上一个固定的key值,即可解决问题
具体的案列代码
<template>
<div class="table">
<div class="tab-item-main">
<div class="tab-item"
:class="{ 'tab-item-click': tabIndex == item.id }"
v-for="(item,index) in enterprisesTab" :key="index"
@click="changeIndex(item.id)">
<div class="tab-item-text">
{{item.name}}
</div>
</div>
</div>
<div>
<el-table :data="tableList" style="width: 100%" border>
<!-- 人工智能榜 -->
<template v-if="tabIndex == 1">
<el-table-column key="1" prop="name" label="名称">
</el-table-column>
<el-table-column key="2" prop="detail" label="详情">
</el-table-column>
<el-table-column key="3" prop="status" label="状态">
</el-table-column>
</template>
<!-- 企业百强榜 -->
<template v-if="tabIndex == 2">
<el-table-column key="4" prop="name" label="企业名称">
</el-table-column>
<el-table-column key="5" prop="detail" label="企业详情">
</el-table-column>
<el-table-column key="6" prop="status" label="状态">
</el-table-column>
</template>
</el-table>
</div>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
tabIndex: 1,
enterprisesTab: [
{
id: 1,
name: "人工智能榜",
},
{
id: 2,
name: "企业百强榜",
},
],
tableList: [
{
id: 1,
name: "测试",
detail: "详情",
status: "已完成",
},
{
id: 1,
name: "测试",
detail: "详情",
status: "已完成",
},
{
id: 1,
name: "测试",
detail: "详情",
status: "已完成",
},
],
};
},
mounted() {},
methods: {
changeIndex(id) {
this.tabIndex = id;
},
},
};
</script>
<style lang="scss" scoped>
.table {
padding: 30px;
border: 1px solid #eee;
margin: 100px auto;
width: 800px;
}
.tab-item-main {
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
column-gap: 12px;
row-gap: 4px;
.tab-item {
padding: 7px 15px;
height: 33px;
background: #f3f8ff;
border-radius: 4px;
transition: all 0.4s;
cursor: pointer;
color: #1d2745;
.tab-item-text {
width: fit-content;
font-size: 14px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
}
}
.tab-item-click {
background: rgb(13, 147, 209);
color: #ffffff;
}
}
</style>
4、v-for之后 this.$refs变成数组
- 普通的ref对象
<div ref="one">第一个ref</div>
<div ref="two">第二个ref</div>
console.log("$refs", this.$refs);
打印结果:
如果想获取ref对象的某个属性,语法为 this.$refs[ref对象名称].属性名
console.log("$refs", this.$refs['one'].innerHTML); //第一个ref
- v-for之后 refs对象
<div class="ref-main">
<div class="ref-item" :ref="`item${index}`"
v-for="(item,index) in textArr" :key="index">
{{ item}}</div>
</div>
data() {
return {
textArr: ["元素选择器", "class选择器", "id选择器", "通配符选择器"],
};
},
console.log("$refs", this.$refs);
打印结果:
每一个ref对象都是一个数组
如果想获取ref对象的某个属性,语法为 this.$refs[ref对象名称][0].属性名
console.log("$refs", this.$refs['item0'][0].innerText);
- 原因分析
假设你的 ref 不是动态的,而是静态的,ref="a",那么不管你执行多少次循环,最后 ref 只会有一个值,所以 vue 为了处理这种情况,会把 v-for 里 ref 转为数组形式
所以当我们使用 v-for 循环动态生成 ref 时,他也会生成一个数组
CSS
相邻兄弟选择器的妙用
场景描述
一列展示多个按钮,每个按钮之间间隔10px
实现方法
每个按钮设置 margin-left为10px,然后单独设置第一个按钮的margin-left为0px;
改良方法(相邻兄弟选择器)
只需设置一次 margin-left
- 缺点:
如果按钮太多,需要换行展示的话,第二行开头的第一个按钮也会有 margin-left
- 解决方法:
使用flex布局、gap属性
效果如下:
这个方法用起来十分方便,不过有个情况下是不能使用flex布局的
就是只展示一行按钮,按钮过多的话,就显示省略号
需要使用以下css属性,会和 display: flex 冲突
因此只能使用相邻兄弟选择器
案例完整代码(vue版本)
<template>
<div class="contain">
<div class="icon-main ellipsis_1">
<div class="icon-item" v-for="(icon,index) in iconArr" :key="index"
:title="icon">
<div class="icon-item-text">{{ icon }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
iconArr: [
"元素选择器",
"class选择器",
"id选择器",
"通配符选择器",
"通配符选择器",
"通配符选择器",
"通配符选择器",
],
};
},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.contain {
padding: 30px;
border: 1px solid #eee;
margin: 100px auto;
width: 800px;
.icon-main {
.icon-item {
cursor: pointer;
display: inline-block;
padding: 0 20px;
height: 40px;
background: #09bef5;
border-radius: 8px;
.icon-item-text {
height: 40px;
line-height: 40px;
text-align: center;
font-size: 15px;
font-family: PingFang SC, PingFang SC-Regular;
color: #fff;
}
}
.icon-item + .icon-item {
margin-left: 10px;
}
}
.ellipsis_1 {
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
-webkit-line-clamp: 1;
}
}
</style>