当前位置:   article > 正文

网站搭建——常用组件及样式_网页组件

网页组件

前言

个人于开发中收集整合的常用组件及样式,主要为element ui

一、CSS

1.div

1.1 圆角

1.1.1 div圆角

border-radius 属性可以设置元素的圆角大小。它接受一个或多个值来指定每个角的圆角半径,值可以是像素、百分比或 em 单位。

.img {
    //盒子圆角
    border-radius: 5PX;
}
  • 1
  • 2
  • 3
  • 4

示例图
在这里插入图片描述

1.1.2 video、img原生组件圆角

配合使用 object-fit: cover,对这些img、video进行保留原始比例的剪切、缩放或者直接进行拉伸等
.video {
border-radius: 10px;
object-fit: cover;
}
在这里插入图片描述

  • 注意:被替换的内容在保持其宽高比的同时填充元素的整个内容框。如果对象的宽高比与内容框不相匹配,该对象将被剪裁以适应内容框。

1.2 边框阴影

使用box-show实现阴影效果,常用于图片、盒子阴影效果

,img{
    /* 方向x 方向y  偏移量  模糊半径  阴影颜色  */
    box-shadow: -5px 8px 1px 1px rgb(209, 209, 209);
    }
  • 1
  • 2
  • 3
  • 4

示例图
在这里插入图片描述

box-shadow 属性还支持以下参数:

  • inset:指定阴影是否在元素内部显示。如果设置了 inset,阴影将在元素内部显示,否则将在元素外部显示。
  • spread:指定阴影的扩散半径,可以是正数、负数或零。正数将使阴影扩大,负数将使阴影缩小。
  • multiple shadows:可以在一个 box-shadow 属性中设置多个阴影效果,多个阴影效果之间用逗号隔开。

1.3 分布

1.3.1 水平分布

使用 display:flex 实现子div相对父div水平分布

//父div使用flex弹性盒模型
.planb {
    display: flex;
    text-align: center;

}
//子div
.planb .imag {
    width: 600px;
    margin: 15px auto;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这里插入图片描述

1.3.2 水平分布自动换行

flex-wrap: wrap;为自动换行,nowrap则为不自动换行

.hzhbdiv {
    flex-wrap: wrap;
    display: flex;
    text-align: center;
    margin: 0 5%;
    padding-left: 2%;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
1.3.3 z轴+水平居中

通过 left: 50%; transform: translateX(-50%); 实现水平居中

.div{
	position: relative;
}
.sonDiv{
	position: absolute;
	left: 50%;
	transform: translateX(-50%);
	bottom: 0;
	z-index: 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
1.3.4 多个div水平居中

通过赋予父元素text-align: center;及子元素display: inline-block;实现多个子元素居中排布

<div style="text-align: center;">
     <div style="display: inline-block;"></div>
     <div style="display: inline-block;"></div>
</div>
  • 1
  • 2
  • 3
  • 4
1.3.5 多个div垂直居中

通过赋予父元素display:flex;及align-items: center;以实现多个子元素垂直居中排布

<div class="container">
  <div class="box">Div 1</div>
  <div class="box">Div 2</div>
  <div class="box">Div 3</div>
</div>

<style>
.container {
  display: flex;
  align-items: center;
}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
1.3.6 水平滚动不换行

使用overflow-x: scroll;控制div水平溢出

<template>
    <div>
        <div class="container">
            <div class="card">1</div>
            <div class="card">2</div>
            <div class="card">3</div>
            <div class="card">4</div>
            <div class="card">5</div>
            <div class="card">6</div>
        </div>
    </div>
</template>

<style scoped>
.container {
    display: flex;
    flex-wrap: nowrap;
    /* 控制水平溢出显示 */
    overflow-x: scroll;
    /* 控制滚动的平滑效果 */
    -webkit-overflow-scrolling: touch;
}

.card {
    width: 400px;
    min-width: 400px;
    height: 200px;
    background-color: bisque;
    margin: 10px;
    white-space: nowrap;
    display: inline-block;
}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

1.4 内容溢出

overflow 是 CSS 的简写属性,其设置了元素溢出时所需的行为——即当元素的内容太大而无法适应它的块级格式化上下文时。

包含的值:

  • visible
    内容不能被裁减并且可能渲染到边距盒(padding)的外部。

  • hidden
    如果需要,内容将被裁减以适应边距(padding)盒。不提供滚动条,也不支持允许用户滚动(例如通过拖拽或者使用滚轮)。内容可以以编程的方式滚动(例如,通过设置 scrollLeft 等属性的值或 scrollTo() 方法), 因此该元素仍然是一个滚动的容器。

  • clip
    类似于 hidden,内容将以元素的边距(padding)盒进行裁剪。clip 和 hidden 之间的区别是 clip 关键字禁止所有滚动,包括以编程方式的滚动。该盒子不是一个滚动的容器,并且不会启动新的格式化上下文。如果你希望开启一个新的格式化上下文,你可以使用 display: flow-root 来这样做。

  • scroll
    如果需要,内容将被裁减以适应边距(padding)盒。无论是否实际裁剪了任何内容,浏览器总是显示滚动条,以防止滚动条在内容改变时出现或者消失。打印机可能会打印溢出的内容。

  • auto
    取决于用户代理。如果内容适应边距(padding)盒,它看起来与 visible 相同,但是仍然建立了一个新的块级格式化上下文。如果内容溢出,则浏览器提供滚动条。

  • overlay 已弃用
    行为与 auto 相同,但是滚动条绘制在内容之上,而不是占据空间。

常用的内容溢出自动添加滚动条:overflow:auto

1.5 悬浮变手

.div:hover{
	cursor:pointer
}
  • 1
  • 2
  • 3

2. 动画

Transform 是 CSS3 中的一个属性,可以用来对元素进行 2D 或 3D 转换。Transform 可以通过设置一系列函数来实现不同的变换效果,Transform 属性不会改变元素的文档流位置,仅仅是在视觉上对元素进行了变换,常用的函数有:

  1. translate():平移,可用来调整元素的位置。使用 translate() 函数可以在水平和垂直方向上移动元素。例如,可以使用 translate(10px, 20px) 来将元素向右移动 10 像素,向下移动 20 像素。

移动+阴影

.article:hover {
    box-shadow: -2px 2px 2px rgba(0, 0, 0, 0.2);
    transform: translate(2px, -2px);
}
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

  1. rotate():旋转,可用来实现元素的旋转效果。使用 rotate() 函数可以将元素旋转指定的角度,角度可以用 deg、grad 或 rad 来表示。例如,可以使用 rotate(45deg) 来将元素顺时针旋转 45 度。

  2. scale():缩放,可用来调整元素的大小。使用 scale() 函数可以将元素的大小按指定的比例进行缩放。例如,可以使用 scale(2, 2) 来将元素在水平和垂直方向上都放大为原来的两倍。

变大+阴影

.img3:hover {
    transform: scale(1.1);
    box-shadow: -5px 5px 5px rgba(0, 0, 0, 0.3);
}
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

  1. skew():倾斜,可用来实现元素的倾斜效果。使用 skew() 函数可以将元素沿着水平或垂直方向进行倾斜。例如,可以使用 skew(30deg, 0) 来将元素在水平方向上倾斜 30 度。

  2. matrix():矩阵变换,可用来实现复杂的变换效果。使用 matrix() 函数可以通过一个 6x1 的矩阵来对元素进行变换。matrix() 函数可以实现 translate()、rotate()、scale() 和 skew() 函数的所有功能,也可以实现更加复杂的变换效果。

3.文本

3.1 两端对齐

实现文本两端对齐(text justify)可以使用 text-align 属性,它有一个属性值为 justify,表示文本两端对齐。

  • 但是,text-align: justify 对于英文单词或字母的排版效果较好,而对于中文排版可能会出现单词和字母之间的间距过大,导致排版效果不美观。因此,我们可以结合使用 word-spacing 和 letter-spacing 属性来调整单词和字母之间的间距,以达到更好的排版效果。
<style>
  .text-justify {
    text-align: justify;
    text-justify: inter-ideograph; /* 中文文本两端对齐 */
    word-spacing: 2px; /* 单词间距 */
    letter-spacing: 1px; /* 字母间距 */
  }
</style>

<div class="text-justify">
  <p>这是一段文本,可以通过 text-align: justify 实现两端对齐的效果。同时,结合使用 word-spacing 和 letter-spacing 属性可以调整单词和字母之间的间距,以达到更好的排版效果。</p>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

上述代码中,text-justify 属性设置为 inter-ideograph 表示中文文本两端对齐。通过调整 word-spacing 和 letter-spacing 属性的值,可以进一步调整单词和字母之间的间距,以达到更好的排版效果。

3.2 下划线到文字的距离

text-underline-offset 属性设置文本装饰下划线(使用 text-decoration 应用)与其原始位置的偏移距离。

/* 单个关键字 */
text-underline-offset: auto;

/* length */
text-underline-offset: 0.1em;
text-underline-offset: 3px;

/* percentage */
text-underline-offset: 20%;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4.针对于不同屏幕大小的样式

4.1 媒体查询

媒体查询(Media Queries)是 CSS3 中的一个特性,用于根据不同的媒体类型、设备特性等条件来应用不同的 CSS 样式。通过媒体查询,可以使得网页在不同的设备上以不同的方式展现,从而实现响应式设计。

媒体查询通过在 CSS 中使用 @media 关键字来定义一个查询,其基本语法如下:

@media mediatype and (条件) {
  /* CSS 样式 */
}
  • 1
  • 2
  • 3

其中,mediatype 可以是 all(所有设备)、print(打印设备)、screen(屏幕设备)、speech(语音阅读器等)等。而条件则是指一些媒体特性,如屏幕宽度、高度、方向、分辨率等。

下面是一个示例,它会在屏幕宽度小于等于 600 像素时,应用特定的样式:

@media screen and (max-width: 600px) {
  body {
    background-color: yellow;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5

上述代码中,@media screen and 表示只应用于屏幕设备,(max-width: 600px) 表示屏幕宽度小于等于 600 像素时,应用样式。这样,当浏览器窗口的宽度小于等于 600 像素时,背景颜色会变成黄色。

4.2 流体布局

流体布局(Fluid Layout)是响应式 Web 设计中常用的一种布局方式,它的特点是页面布局随着浏览器窗口大小的改变而自动调整,以适应不同屏幕和设备的显示。

下面是一个示例,它的宽度和高度将会随父div的大小二变化

.ullist img {
    width: 80%;
    height: 100%;
}
  • 1
  • 2
  • 3
  • 4

在流体布局中,页面元素的宽度不是固定的,而是使用百分比、em、rem 等相对单位来设置,使得页面元素可以根据浏览器窗口大小进行自适应。具体来说,流体布局常用的技术包括以下几种:

  1. 使用百分比:将页面元素的宽度设置为百分比,以相对于其父元素的宽度计算。例如,将一个容器的宽度设置为 80%,则该容器的宽度将会随着其父元素的宽度改变而自适应。

  2. 使用 em 和 rem:将页面元素的宽度设置为 em 或 rem,以相对于其父元素或根元素的字体大小计算。例如,将一个容器的宽度设置为 20em,则该容器的宽度将会随着其父元素的字体大小改变而自适应。

  3. 使用 max-width 和 min-width:使用 max-width 和 min-width 属性来限制页面元素的最大和最小宽度,以避免在屏幕过大或过小时出现不必要的空白或重叠现象。

通过使用流体布局,可以使得页面在不同设备和屏幕大小下都能呈现出最佳的布局效果,提升用户的浏览体验。不过,流体布局也有其局限性,例如在设计某些特定功能或交互时可能需要使用绝对布局或固定宽度的元素,这时需要在设计时进行权衡和取舍。

4.3 window.innerWidth

window.innerWidth 是一个 JavaScript 属性,返回当前窗口(浏览器)的宽度,即可视区域宽度,以像素为单位。它不包括滚动条的宽度,如果需要包含滚动条的宽度,可以使用 document.documentElement.clientWidth 属性。

以函数通过window.innerWidth当前窗口(浏览器)的宽度并作出相应的措施

该函数须在created等钩子函数调用才能生效

get() {
            this.$nextTick(() => {
                const screenWidth = window.innerWidth
                if (screenWidth < 768) {
                    this.abImg = 'https://i.tosoiot.com/20230509/t/8f00a73bf95a98df.jpg'
                }
            })
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

5.滚动条样式修改

/* 隐藏滚动条 */
/*
::-webkit-scrollbar {
    display: none;
}
*/

/* 滚动条样式 */
::-webkit-scrollbar {
  width: 10px; /* 滚动条宽度 */
  height: 10px; /* 滚动条高度 */
}

/* 滚动条轨道 */
::-webkit-scrollbar-track {
  background: #f1f1f1; /* 滚动条轨道背景色 */
}

/* 滚动条thumb */
::-webkit-scrollbar-thumb {
  background: #888; /* 滚动条thumb背景色 */
}

/* 滚动条hover状态的thumb */
::-webkit-scrollbar-thumb:hover {
  background: #555; /* 滚动条hover状态的thumb背景色 */
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这里插入图片描述

6.z轴

6.1 相对父元素

.div{
	position: relative;
}
.sondiv{
	position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100px;
    z-index: 1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

7.a标签

text-decoration​ 属性是用来设置 a 标签的划线属性的。
其属性值有:

  • none:去掉下划线underline:设置下划线
  • overline:在文本上方设置线条
  • line-through:在文本中间设置线条
  • initial:默认值
  • inherit:从父元素中继承

7.1 去除下划线

a{
text-decoration: none;
}
  • 1
  • 2
  • 3

二、vue

JS相关

1. onUpdated触发事件递归问题

我们在一些情况下可能会需要在onUpdated中调用事件,但该事件会触发onUpdated从而导致递归问题

解决办法:

找到一个该事件在不同的调用中不同的参数,以此作为判断来调用事件

//不同的调用中不同的参数
const isUpdateId = ref(0)

function getFolders() {
    Axios.post(
        '/getFolder/Img',
        {
            collection_folder_id: localStorage.folderId
        }
    )
        .then(response => {
            console.log(response.data)
            foldersImg.value = response.data.data.images
            isUpdateId.value = localStorage.folderId
        })
        .catch(error => {
            console.error(error);
        });
}
onUpdated(() => {
	//以此作为判断来调用事件
    if(isUpdateId.value != localStorage.folderId){
        getFolders()
    }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

Vue2

1. 修改title

通过在vue.config.js中的module.exports = defineConfig({})中添加以下代码进行修改

chainWebpack: config =>{
    config.plugin('html').tap(args => {
        args[0].title = 'you title';
        return args;
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

vue3

三、element-ui

依赖如下

  "dependencies": {
    "axios": "^1.3.4",
    "core-js": "^3.8.3",
    "element-ui": "^2.4.5",
    "vue": "^2.6.14",
    "vue-axios": "^2.1.5",
    "vue-router": "^3.5.1",
    "vuex": "^3.6.2"
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

1.el-input

1.1 el-input 回车事件

使用 @keyup.enter.native=“调用的函数” 回车调用函数

<el-input v-model="prompt" placeholder="您有什么想问的吗?"  
@keyup.enter.native="gpt()">
  • 1
  • 2

1.2 el-input type=“textarea” 自动换行

通过设置 autosize 属性可以使得文本域的高度能够根据文本内容自动进行调整,并且 autosize 还可以设定为一个对象,指定最小行数和最大行数。

<el-input
  type="textarea"
  :autosize="{ minRows: 2, maxRows: 4}"
  placeholder="请输入内容"
  v-model="textarea2">
</el-input>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1.3 el-input 密码输入小眼睛

通过 el-input 的 show-password 属性实现密码的显示

<!-- show-password小眼睛 -->
<el-input style="height: 40px;margin-bottom: 4%;" v-model="password"
type="password" placeholder="请输入密码" show-password /> 
  • 1
  • 2
  • 3

在这里插入图片描述

2.去除竖向导航栏右边的边框

在这里插入图片描述

.el-menu {
	border-right:0!important;
}
  • 1
  • 2
  • 3

3.el-table

3.1 图片插入

通过prop获取返回数据,通过slot-scope传递给img标签

<el-table :data="tableData" :header-cell-style="{ 'text-align': 'center' }">
	<el-table-column label="文章">
    	<el-table-column prop="articleId" label="ID" width="100px" />
        <el-table-column label="图片" width="150px">
        	<template slot-scope="scope">
            	<img :src="scope.row.articleImg" style="width: 100%;" />
            </template>
        </el-table-column>
        <el-table-column prop="articleTitle" label="标题" />
        <el-table-column prop="articleIntroduction" label="简介" />
        <el-table-column prop="articleContent" label="描述" />
	</el-table-column>
</el-table>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

示例图
在这里插入图片描述

3.2 文字居中

1.header-cell-style:表头单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有表头单元格设置一样的 Style。
2.cell-style:单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有单元格设置一样的 Style。
3.row-style:行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。

<el-table class="cs1" :data="profitData" 
	:header-cell-style="{ 'text-align': 'center' }"
    :cell-style="{ 'text-align': 'center' }">
    <el-table-column label="利润计算结果">
    	<el-table-column prop="commission" label="佣金" />
    	<el-table-column prop="advertisement" label="广告费" />
    	<el-table-column prop="total" label="产品总成本" />
    	<el-table-column prop="profit" label="利润" />
    	<el-table-column prop="profitRatio" label="利润率" />
    </el-table-column>
</el-table>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.3 取消tr:hover高亮

::v-deep .el-table tbody tr:hover>td {
    background-color: transparent!important;
}
  • 1
  • 2
  • 3

4.图片轮播

4.1 默认

在这里插入图片描述

4.2 卡片模式

arrow=“never” indicator-position=“none” interval=“0” type=“card”

在这里插入图片描述

代码如下

<template>
    <!-- arrow   切换箭头的显示时机;indicator-position	指示器的位置;interval	自动切换的时间间隔,单位为毫秒 ;type="card"   卡片化-->
    <el-carousel id="terrace" arrow="never" indicator-position="none" interval="0" type="card" height="600px">
        <el-carousel-item v-for="item in imgList" :key="item.id">
            <el-image :src="item.idView" class="image" style="width: 100%; height: 600px;" />
        </el-carousel-item>
    </el-carousel>
</template>

<script>
export default {
    data() {
        return {
            imgList: [
                // 后端图片地址
                { id: 0, idView: './img/1.jpg' },
                { id: 1, idView: './img/2.jpg' },
                { id: 2, idView: './img/3.jpg' },
                { id: 3, idView: './img/4.jpg' },
                { id: 4, idView: './img/5.jpg' },
                { id: 5, idView: './img/6.jpg' }
            ]
        };
    }
}
</script>

<style>
#terrace {
    margin: 20px 10px;
    margin-bottom: 50px;
}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

4.3 动画效果

card模式的动画不是将当前轮播项放大而是将其它的缩小到0.83,所以如果想修改轮播动画需要将当前轮播想也进行缩小并添加想要的动画

  • card模式的轮播图
<el-carousel @change="handleCarouselChange" :autoplay=false indicator-position="none" type="card" arrow="never"
            height="600px">
            <el-carousel-item v-for="(item, index) in carouselItems" :key="index">
                <h1>{{ item }}</h1>
            </el-carousel-item>
        </el-carousel>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 获取当前轮播项并修改其动画
handleCarouselChange(index) {
            const items = document.querySelectorAll('.el-carousel__item');
            items.forEach(item => {
                item.style.boxShadow = 'none';
            });
            setTimeout(() => {
                const currentItem = this.$el.querySelector(".el-carousel__item:nth-child(" + (index + 1) + ")");
                if (currentItem) {
                    currentItem.style.boxShadow = "12px 8px 10px #a4b3c086"
                    currentItem.style.transform = "scale(0.88) translate(79%, -40px)";
                    currentItem.style.transition = "transform 0.3s"; 
                }
            }, 10);
        },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 通过mounted()对第一个轮播项进行修改
mounted() {
        this.handleCarouselChange(0);
    }
  • 1
  • 2
  • 3

在这里插入图片描述

4.4 可能会出现的bug

indicator-position属性定义了指示器的位置。默认情况下,它会显示在走马灯内部,设置为outside则会显示在外部;设置为none则不会显示指示器。

当el-carousel的高度固定的时候,indicator-position设置为outside可能会出现内容高度大于走马灯的高度以至于出现下拉框的情况,解决方法是设置indicator-position属性为默认即可

5.返回顶部

默认

在这里插入图片描述

代码如下

<el-backtop></el-backtop>
  • 1

6.el-menu导航栏

el-menu 是 Element UI 框架中的一个组件,用于创建菜单导航。它提供了多种功能和样式选项,可以轻松创建水平或垂直的菜单,并支持嵌套子菜单。el-menu 组件通常与 el-menu-item 和 el-submenu 组件一起使用。

6.1 mode

mode 是 el-menu 组件的一个属性,用于设置菜单的显示模式。它决定了菜单是以水平布局还是垂直布局显示。

mode 属性有两个可选值:

“horizontal”:水平布局模式。菜单项水平排列,通常用于顶部导航栏或水平工具栏的菜单。在水平模式下,菜单项从左到右水平排列,适合于较宽的容器。
在这里插入图片描述

“vertical”:垂直布局模式。菜单项垂直排列,通常用于侧边栏或垂直导航栏的菜单。在垂直模式下,菜单项从上到下垂直排列,适合于较窄的容器。
在这里插入图片描述

6.2 collapse

collapse 是 el-menu 组件的一个属性,用于设置菜单是否可折叠(展开和收起)。

当 collapse 属性设置为 true 时,菜单将具有折叠功能,用户可以通过点击折叠按钮或菜单项来展开和收起菜单的子菜单。当菜单处于折叠状态时,子菜单将被隐藏,只显示菜单的图标和文本。

使用折叠菜单可以节省页面空间,在有限的空间内展示较多的菜单选项。折叠菜单通常用于侧边栏布局或移动设备上的导航栏。
在这里插入图片描述

6.3 menu-trigger

menu-trigger 是 el-menu 组件的一个属性,用于设置触发菜单展开和收起的方式。

默认情况下,菜单的展开和收起是通过鼠标悬停的方式触发的,即当鼠标悬停在菜单上时,菜单将展开,鼠标离开时菜单将收起。

通过设置 menu-trigger 属性,可以改变菜单的触发方式。menu-trigger 属性支持以下取值:

“hover”: 默认值,表示通过鼠标悬停触发菜单的展开和收起。
“click”: 表示通过鼠标点击触发菜单的展开和收起。当用户点击菜单时,菜单将展开,再次点击菜单时,菜单将收起。

三、Apache ECharts

Apache ECharts 是基于 JavaScript 的开源可视化图表库,它可以将数据渲染成图表

1.安装

npm install echarts --save
  • 1

2.引入

main.js中引入(此处展示的为5.X的引入,4.X的引入应改为import echarts from ‘echarts’)

import * as echarts from 'echarts'
  • 1

3.使用案例

div /

<div style="display: flex;flex-wrap: wrap;">
	<div id="eChartsId1" style="width: 900px; height: 600px;"></div>
	<div id="eChartsId2" style="width: 900px; height: 600px;"></div>
</div>
  • 1
  • 2
  • 3
  • 4

JavaScript / methods

import * as echarts from 'echarts';

//省略其它代码......

		tb() {
		//指定图表渲染位置
            let myChart = echarts.init(document.getElementById("eChartsId1"));
            myChart.setOption({
                title: {
                    text: "ysd",
                    fontSize: 24,
                    left: '10%'
                },
                //x轴
                xAxis: {
                    name: 'a',
                    data: ['A', 'B', 'C', 'D', 'E', 'F']
                },
                //y轴
                yAxis: {
                    name: 'b',
                },
                series: [
                    {
                        name: 'yyy',
                        data: [16, 22, 28, 23, 32, 28],
                        type: 'line',
                        stack: 'line1',
                        smooth: true
                    },
                    {
                        name: 'sss',
                        data: [15, 15, 23, 25, 18, 28],
                        type: 'line',
                        stack: 'line2',
                    }
                ],
                tooltip: {
                    trigger: 'axis',
                    backgroundColor: 'rgba(32, 33, 36,.7)',
                    borderColor: 'rgba(32, 33, 36,0.20)',
                    borderWidth: 1,
                    textStyle: {
                        color: '#fff',
                        fontSize: '12'
                    }
                }
            });
            let myChart1 = echarts.init(document.getElementById("eChartsId2"));
            myChart1.setOption({
                xAxis: {
                    data: ['A', 'B', 'C', 'D', 'E']
                },
                yAxis: {},
                series: [
                    {
                        name: 'ddd',
                        data: [10, 22, 28, 23, 19],
                        type: 'line',
                        smooth: true,
                        areaStyle: {
                            color: 'lightblue',
                            opacity: 0.5
                        }
                    }
                ],
                tooltip: {
                    trigger: 'axis',
                    backgroundColor: 'rgba(32, 33, 36,.7)',
                    borderColor: 'rgba(32, 33, 36,0.20)',
                    borderWidth: 1,
                    textStyle: {
                        color: '#fff',
                        fontSize: '12'
                    }
                }
            });
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

展示图

在这里插入图片描述

四、实用模块

1.登录注册 模块

该组件为简单基础的一个登录模块,使用v-if实现登录和注册之间的切换,并使用transition以实现切换动画
在这里插入图片描述
在这里插入图片描述

代码如下

<template>
  <div>
    <div style="width: 100%; height: 100%; background-size: 100%; position: fixed;">
      <div id="loginFrom">
        <!-- 动画对象 -->
        <transition name="fade" mode="out-in">
          <div :key="isShow">
            <div v-if="isShow">
              <!-- 登录 -->
              <el-form id="loginForm">
                <h1 style="font-size: 42px;margin: 4% auto;">登录</h1>
                <el-form-item>
                  <p class="text">账号</p>
                  <el-input style="height: 42px;" v-model.number="userId" placeholder="请输入账号" type="text" />
                </el-form-item>
                <el-form-item>
                  <p class="text">密码</p>
                  <!-- show-password小眼睛 -->
                  <el-input style="height: 40px;margin-bottom: 4%;" v-model="password" type="password" placeholder="请输入密码" show-password />
                </el-form-item>
                <el-button @click="Login()">登录</el-button>
                <el-button @click="toChange()">注册</el-button>
              </el-form>
            </div>
            <div v-else>
              <!-- 注册-->
              <el-form id="registerForm">
                <h1 style="font-size: 42px;margin: 4% auto;">注册</h1>
                <el-form-item>
                  <p class="text">用户名</p>
                  <el-input style="height: 42px;" v-model="userName" placeholder="请输入用户名" type="text" />
                </el-form-item>
                <el-form-item>
                  <p class="text">密码</p>
                  <el-input style="height: 40px;margin-bottom: 4%;" v-model="password" type="password" placeholder="请输入密码"
                    show-password />
                </el-form-item>
                <el-form-item>
                  <p class="text">确认密码</p>
                  <el-input style="height: 40px;margin-bottom: 4%;" v-model="password2" type="password"
                    placeholder="请再次输入密码" show-password />
                </el-form-item>
                <el-button @click="toChange()">登录</el-button>
                <el-button @click="Register()">注册</el-button>
              </el-form>
            </div>
          </div>
        </transition>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      userId: '',
      userName: '',
      password: '',
      password2: '',
      isShow: true,
    }
  },
  methods: {
    toChange() {
      this.isShow = !this.isShow;
    },
    Login() {
      if (this.userId === "") {
        this.$alert("账号不能为空", {
          confirmButtonText: '确定',
        });
      } else if (this.password === "") {
        this.$alert("密码不能为空", {
          confirmButtonText: '确定',
        });
      } else {
        this.$axios.post(
          "/user/login",
          this.$qs.stringify({
            userId: this.userId,
            userPassword: this.password
          })
        )
          .then((res) => {
            //登录成功
            } else {
              //登录失败
            }
          });
      }
    },
    Register() {
      if (this.userName === "") {
        this.$alert("用户名不能为空", {
          confirmButtonText: '确定',
        });
      } else if (this.password.length < 6) {
        this.$alert("密码不能小于6位", {
          confirmButtonText: '确定',
        });
      } else if (this.password === this.password2) {
        this.$axios.post(
          "/user/register",
          this.$qs.stringify({
            userName: this.userName,
            userPassword: this.password
          })
        )
          .then((res) => {
            this.$alert(res.data, {
              confirmButtonText: '确定',
            });
          });
      } else {
        this.$alert("两次密码不同", {
          confirmButtonText: '确定',
        });
      }
    }
  },
  components: {
  }
}
</script>

<style>
#loginFrom {
  margin: 3% auto;
  padding: 3%;
  min-width: 300px;
  max-width: 25%;
  text-align: center;
  background-color: rgba(255, 255, 255, 0.856);
  border-radius: 5%;
  color: rgb(0, 0, 0);
  font-weight: 800;
}

.text {
  font-size: 20px;
  margin: 0;
  text-align: left;
}

/* 进出动画时间 */
.fade-enter-active,
.fade-leave-active {
  transition: all .8s;
}

/* 进出动画效果 */
.fade-enter,
.fade-leave-to {
  transform: translateX(20px);
  opacity: 0;
}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159

2.轮播图 模块

此轮播图模块较为复杂,它实现了电脑屏幕和手机屏幕两套不同的图片轮播,且手机屏幕下可以通过滑动切换图片

<template>
    <div class="carousel-wrapper" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
        <el-carousel ref="carousel" :interval="3000" :style="{ height: screenheight + 'px' }" :arrow="isMobile"
            :indicator-position="isMobile ? 'none' : 'outside'">
            <el-carousel-item v-for="item in imgs" :key="item.id" style="height: 100%;">
                <el-image :src="item.src" class="carousel-img" />
            </el-carousel-item>
        </el-carousel>
    </div>
</template>
<script>
export default {
    data() {
        return {
            imgs: [
                {
                    id: 1,
                    src: '1.jpg',
                },
                {
                    id: 2,
                    src: '2.jpg',
                },
                {
                    id: 3,
                    src: '3.jpg',
                },
            ],
            screenheight: 600,
            isMobile: false,
            startX: 0,
            startY: 0,
            endX: 0,
            endY: 0,
        };
    },
    created() {
        this.calculateHeight();
        window.addEventListener('resize', this.calculateHeight);
    },
    beforeDestroy() {
        window.removeEventListener('resize', this.calculateHeight);
    },
    methods: {
        handleTouchStart(e) {
            this.startX = e.touches[0].clientX;
            this.startY = e.touches[0].clientY;
        },
        handleTouchMove(e) {
            this.endX = e.touches[0].clientX;
            this.endY = e.touches[0].clientY;
        },
        handleTouchEnd() {
            const distanceX = this.endX - this.startX;
            const distanceY = this.endY - this.startY;
            if (Math.abs(distanceX) > Math.abs(distanceY)) {
                if (distanceX > 0) { 
                    this.$refs.carousel.prev();
                } else { 
                    this.$refs.carousel.next();
                }
            }
        },
        calculateHeight() {
            const windowWidth = window.innerWidth;
            this.isMobile = windowWidth < 768;  
            if (this.isMobile) {
                this.imgs = [
                    {
                        id: 1,
                        src: '1.jpg',
                    },
                    {
                        id: 2,
                        src: '2.jpg',
                    },
                    {
                        id: 3,
                        src: '3.jpg',
                    },
                    {
                        id: 4,
                        src: '4.jpg',
                    },
                ];
            } else {
                this.imgs = [
                    {
                        id: 1,
                        src: '1.jpg',
                    },
                    {
                        id: 2,
                        src: '2.jpg',
                    },
                    {
                        id: 3,
                        src: '3.jpg',
                    },
                ];
            }
        },
    },
};
</script>

<style>
.el-carousel__container {
    height: 100% !important;
    margin-bottom: 0;
    overflow: hidden;
}
</style>

<style scoped>
.carousel-wrapper {
    width: 100%;
}

.carousel-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126

3.div进出场动画

检测div的位置以实现当其进入或离开视窗的时候触发动画

<template>
    <div class="scroll-container" @scroll="handleScroll">
        <div class="content">Content 0</div>
        <div class="content">Content 1</div>

        <!-- 进场和退场动画的目标 -->
        <div class="content animated-content" ref="animatedContent">
            Content 2 - with enter and exit animation
        </div>

        <div class="content">Content 3</div>
        <div class="content">Content 4</div>
    </div>
</template>
  
<script>
export default {
    methods: {
        // 进场动画
        animateEnter(el) {
            el.style.transition = 'opacity 0.5s, transform 0.5s';
            el.style.opacity = 1;
            el.style.transform = 'translateY(0)';
        },
        // 退场动画
        animateLeave(el) {
            el.style.transition = 'opacity 0.5s, transform 0.5s';
            el.style.opacity = 0;
            el.style.transform = 'translateY(-30px)';
        },
        // 处理滚动事件
        handleScroll() {
            const animatedContent = this.$refs.animatedContent;
            const rect = animatedContent.getBoundingClientRect();
            const windowHeight = window.innerHeight;

            // 判断元素是否在视窗内部
            if (
                rect.top < windowHeight &&      // 元素顶部在视窗内
                rect.bottom > 0                // 元素底部在视窗外
                // && rect.bottom - windowHeight < 0 // 元素底部在视窗内
            ) { 
                this.animateEnter(animatedContent);
            } else {
                this.animateLeave(animatedContent);
            }
        },
    },
};
</script>
  
<style scoped>
.scroll-container {
    height: 100vh;
    overflow-y: scroll;
}

.content {
    height: 500px;
    padding: 20px;
    border: 1px solid #ccc;
    margin-bottom: 20px;
}

.animated-content {
    opacity: 0;
    transform: translateY(30px);
}
</style>
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

4. div横向自动循环滚动

<template>
  <div>
    <div id="PartnersFont">
    </div>
    <div class="carousel" ref="all">
      <div v-for="(item, index) in tableData" :key="index" class="carousel-item"
           :style="'transform: translateX(' + item.translateNum + 'px)'" ref="demoItem" @mouseover="mouseOver"
           @mouseleave="mouseLeave">
        <div>{{ item.name }}</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          name: '1'
        }, {
          name: '2'
        }, {
          name: '3'
        }, {
          name: '4'
        }, {
          name: '5'
        }
      ],
      translateNum: 0,
      timer: null
    }
  },
  mounted() {
    this.search()
  },
  beforeDestroy() {
    window.clearTimeout(this.timer)
  },
  methods: {
    search() {
      for (var i = 0; i < this.tableData.length; i++) {
        this.$set(this.tableData[i], 'translateNum', 0)
      }

      this.$nextTick(() => {
        for (var j = 0; j < this.tableData.length; j++) {
          this.$set(this.tableData[j], 'indexLeft', this.$refs.demoItem[j].offsetLeft)
        }

        this.roll()
      })
    },

    roll() {
      this.timer = setInterval(() => {
        for (var i = 0; i < this.tableData.length; i++) {
          if (document.body.clientWidth - this.tableData[i].translateNum - this.tableData[i].indexLeft < 0) {
            this.$set(this.tableData[i], 'translateNum', this.$refs.all.offsetLeft - this.tableData[i].indexLeft - 220)
          }
          this.$set(this.tableData[i], 'translateNum', this.tableData[i].translateNum + 2)
        }
      }, 20)
    },

    mouseOver() {
      window.clearTimeout(this.timer)
    },

    mouseLeave() {
      this.roll()
    }

  }
}
</script>

<style scoped>
.carousel {
  width: 100%;
  height: 300px;
  margin: 20px auto;
  overflow: hidden;
  display: flex;
  justify-content: left;
}

.carousel-item {
  border-radius: 10px;
  padding: 10px;
  width: 200px;
  min-width: 200px;
  height: 100px;
  text-align: center;
  margin: 10px 20px;
  background-color: rgba(156, 200, 238, 0.815);
}

#PartnersFont {
  text-align: center;
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/853362
推荐阅读
相关标签
  

闽ICP备14008679号