Atualização 2023.2.7
Essa abordagem tem muitas falhas. Existem outras soluções melhores, que foram atualizadas no novo artigo. Amigos interessados podem ler o novo artigo ↓
Este é um efeito de sublinhado feito com Vue, nenhum outro plugin é usado
Índice
1. Faça uma barra de navegação inicial
Este é o efeito final ↓
No início verifiquei as práticas de outras pessoas na Internet, e a maioria delas foi realizada usando a borda inferior, ou método de pseudoelemento + borda.
Se você simplesmente usar a borda, o comprimento da borda muda de acordo com o comprimento do conteúdo da opção, o que não é particularmente bom. Embora possa ser resolvido escrevendo uma borda em um pseudoelemento, acho que há uma desvantagem em fazendo isso, ou seja, a linha de borda não pode ser definida. Cantos arredondados, então a estética ficará um pouco...
Voltando ao assunto, percebi assim↓
1. Faça uma barra de navegação inicial
<body>
<div id="app">
<div class="nav">
<!-- 标题列表 -->
<div class="nav-list">
<div v-for="(item, index) in navList" :key="index">{
{ item }}</div>
</div>
<!-- 下划线 -->
<div class="nav-line"></div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: "#app",
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
},
});
</script>
<style>
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.nav {
position: relative;
}
.nav-list {
width: 100%;
height: 50px;
display: flex;
justify-content: space-around;
align-items: center;
}
.nav-line {
width: 18px;
height: 4px;
border-radius: 2px;
background-color: red;
position: absolute;
bottom: 0;
}
</style>
O efeito mostrado acima é este
2. Adicione estilo de clique
Primeiro de tudo, precisamos adicionar um evento de clique a cada opção da navegação e, em seguida, fazer com que o item clicado mude de cor quando clicado
- Adicionar evento e classe dinâmica na parte HTML
<div class="nav-list">
<div v-for="(item, index) in navList" :key="index" @click="click(index)" :class="{ active : index==current }">{
{ item }}</div>
</div>
- Adicione variáveis e métodos às instâncias Vue
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
current: 0,
},
methods: {
// 点击时执行
click(index) {
this.current = index;
this.lineMove();
},
// 计算下划线应该移动的距离
lineMove() {
},
},
- Adicione estilo à parte CSS
.active {
color: red;
font-weight: bold;
}
Então obtemos algo assim
Depois de concluir as duas primeiras etapas, a cor da fonte mudou e a próxima etapa é fazer o sublinhado se mover junto com ela
3. Sublinhar o movimento
- Adicione estilo dinâmico ao sublinhado na parte HTML
Como o posicionamento absoluto foi adicionado ao sublinhado antes, você pode usar a propriedade left para deslocamento aqui
<div class="nav-line" :style="{left:X+'px',transform : 'translateX(-50%)'}"></div>
Claro, você também não pode usar left, e apenas usar translateX() que altera o atributo transform para obter o mesmo efeito↓
<!-- 只使用transform的写法 -->
<div class="nav-line" :style="{transform : `translateX(${X}px) translateX(-50%)`}"></div>
Observe que translateX() deve ser colocado entre aspas '' ou string de modelo ``, caso contrário, um erro será relatado. translateX(-50%) é mover o sublinhado para a esquerda em 50% para garantir o alinhamento. Todos devem entender esse
- Adicione a variável X e o método lineMove na instância Vue
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
X: 0,
current: 0,
},
methods: {
// 点击时执行
click(index) {
this.current = index;
this.lineMove();
},
// 计算下划线应该移动的距离
lineMove() {
// 导航栏的宽度,因为是100%所以就是屏幕宽度
let width = document.body.clientWidth;
// 每个选项栏的宽度 = 导航栏宽度/选项个数
let divWidth = width / this.navList.length;
// 半个选项栏宽度
let halfDivWidth = divWidth / 2;
// 下划线移动的距离 = 半个选项栏宽度 + (单个选项栏宽度*当前index)
this.X = halfDivWidth + divWidth * this.current;
},
},
Aqui vamos largura = a largura de .nav-list, porque definimos a largura de .nav-list como 100% em css antes, então obtive a largura atual da tela no exemplo.
- CSS adiciona efeito de transição ao sublinhado
.nav-line {
width: 18px;
height: 4px;
border-radius: 2px;
background-color: red;
position: absolute;
bottom: 0;
transition: 0.3s all;
}
obter o efeito
Depois de fazer isso, você pode ver que o efeito foi realizado, mas ainda há um pequeno problema - a posição do sublinhado está errada quando a página é inicializada, está no lado esquerdo da tela e metade dele transborda a tela, a razão também é óbvia, o valor inicial que definimos para a variável X é 0.
Resolva o problema: execute o método lineMove uma vez no ciclo de vida criado
created() {
// 避免页面初始化会有显示问题,初始加载时就执行一次该方法
this.lineMove();
},
Nota: Recomenda-se executar no ciclo criado e não no ciclo montado, pois o montado é executado após a conclusão do carregamento inicial da página, portanto, quando executado no montado, veremos o sublinhado ficar brevemente no lado esquerdo do a tela no início.
Obtenha o efeito final ↓
código final
<body>
<div id="app">
<div class="nav">
<!-- 标题列表 -->
<div class="nav-list">
<div v-for="(item, index) in navList" :key="index" @click="click(index)" :class="{ active : index==current }">{
{ item }}</div>
</div>
<!-- 下划线 -->
<div class="nav-line" :style="{left:X+'px',transform : 'translateX(-50%)'}"></div>
<!-- <div class="nav-line" :style="{transform : `translateX(${X}px) translateX(-50%)`}"></div> -->
</div>
</div>
</body>
<script>
var vm = new Vue({
el: "#app",
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
X: 0,
current: 0,
},
methods: {
// 点击时执行
click(index) {
this.current = index;
this.lineMove();
},
// 计算下划线应该移动的距离
lineMove() {
// 导航栏的宽度,因为是100%所以就是屏幕宽度
let width = document.body.clientWidth;
// 每个选项栏的宽度 = 导航栏宽度/选项个数
let divWidth = width / this.navList.length;
// 半个选项栏宽度
let halfDivWidth = divWidth / 2;
// 下划线移动的距离 = 半个选项栏宽度 + (单个选项栏宽度*当前index)
this.X = halfDivWidth + divWidth * this.current;
},
},
created() {
// 避免页面初始化会有显示问题,初始加载时就执行一次该方法
this.lineMove();
},
});
</script>
<style>
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.nav {
position: relative;
}
.nav-list {
width: 100%;
height: 50px;
display: flex;
justify-content: space-around;
align-items: center;
}
.active {
color: red;
font-weight: bold;
}
.nav-line {
width: 18px;
height: 4px;
border-radius: 2px;
background-color: red;
position: absolute;
bottom: 0;
transition: 0.3s all;
}
</style>
Precauções
- O estilo flexível da barra de navegação.nav -list deve usar justify-content: space-around; caso contrário, o cálculo subsequente da distância do movimento do sublinhado será impreciso
- Você pode definir o estilo do sublinhado ou usar o atributo background-image para fazer um sublinhado gradiente
- Se o número (comprimento) das opções na barra de navegação for diferente, o movimento do sublinhado também será impreciso. É melhor unificar o número (comprimento) das opções, ou cada mestre pode resolver sozinho
- Bem-vindo a deixar uma mensagem, não pulverize se não gostar