前端常见问题细节汇总 & 简写属性 & JS易忘点

CSS易忘细节汇总 & 简写属性

布局原则

  • 先行后列
  • 先结构后样式

所有标签都是盒子

无论是行内元素,行内块元素还是块元素都是盒子。
区别主要在于能否直接指定宽高默认排列方式
因此,行内(块)元素同样能使用 margin padding 那些属性

行内(块)元素水平对齐

text-align: left/center/right

块元素水平居中

  1. 给块级元素设置宽度;不设置宽度,占据一整行,没有居中的概念
  2. 左右外边距设置为 auto;
    margin 0 auto;
    

图片(行内块)底部空白缝隙问题

行内块元素默认与文字的基线对齐,因文字基线下面还有一小部分长度,因此基线以下的部分对齐到行内块这边就表现为下边有个缝隙。
此时可以使用 vertical-align: baseline/bottom/top/middle设置对齐方式

定位元素居中

使用 定位+margin负值

 position: absolute;
 top: 50%;
 left: 50%;
 margin-top: -50px;
 margin-left: -100px;
 width: 200px;
 height: 100px;

使用 css函数 calc计算定位位置

position: absolute;
top: calc(50% - 50px);
left: calc(50% - 100px);
width: 200px;
height: 100px;

使用2d位移(推荐)

 position: absolute;
 top: 50%;
 left: 50%;
 transform: translate(-100%, -50%);
 width: 200px;
 height: 100px;

定位对齐方式

元素启用定位时,靠哪一边对齐,尺寸发生变化时,向另一个方向发生变化

单行文本,垂直居中

行高设置为所在盒子的高度 line-height = 父盒子高度
或者父盒子不设置高度,由子盒子的行高来撑起父盒子的高度。

注意C3盒子模型中文字垂直居中问题

由于C3盒子模型宽高,包括了边框;而文字行高是基于盒子内容而言的。
一次C3盒子模型中,要垂直居中,行高 = 盒子高度 - 上下边框的大小

图片相邻文字垂直对齐方式

图片默认与文字基线对齐,所谓基线,就是以前写拼音的中间那一条线。
可以通过图片的CSS属性 vertical-align 修改图片与文字的对齐方式
文字和图片不能浮动,如果有浮动,那么这个属性无法生效

vertical-align: bottom / baseline / middle / top

行高最终作用在文字上面,而非任何标签

如果文字在行内元素中,那么只会影响该元素的上下空间,而不会撑大元素本身(因为行内元素没有设置宽高一说
如果文字在块元素(包括行内块)中,那么会撑大元素本身。

padding 和 border 影响盒子大小

此二者只影响传统盒模型下的盒子大小。
在此基础之上。

  • padding只影响在对应方向上值定了尺寸的大小。
  • border在水平方向只影响值定了宽度的盒子的宽度;而高度无论是否值定,都会影响

再加一点,在边框盒模型(目前用得更多)下,paddig只对指定了尺寸的盒子没效果,对于未指定尺寸的行内(块)依然有效

根据字数不同生成长度不同的盒子区域(利用padding撑大盒子)

  1. 将每个菜单盒子转为行内块,不要设置宽度
  2. 设置相同的padding值
  3. 在盒子内录入各自的菜单名称,让文字 和 padding 撑开盒子

不确定尺寸或者内部元素个数是动态的父盒子不要指定固定的尺寸,应该由实际内容撑开。

行内(块)元素中间的空隙

当行内(块)元素没有写在一行时,它们之间默认会有一个空隙。
解决办法有以下几种方法:

  • 使用margin-left 或者 margin-right 负值让元素靠一起
  • 将行内块元素的父元素font-size设置为0,然后在行内块内部再设置需要的字体大小
  • 浮动
  • 使用flex布局
  • 源代码级别,将两个标签连接的字符(><SPAN>)放在同一行
  • 源代码级别,用注释连接两行,在注释中换行

浮动盒子内容动态时,无法指定父盒子高度,此时引起的父盒子高度塌陷问题

标准流盒子内的盒子都浮动后,无法撑起父盒子的高度,导致后面的元素被浮动元素覆盖。
解决:
在子盒子浮动的最后 清除浮动

在最后一个元素浮动后,可能需要清除浮动,否则有可能影响后续的标准流盒子。
li 元素浮动 导致 box 盒子高度为0 ,进而影响了 footer 盒子,飘到 li 列表里面去了。

<div class="box">
  <ul>
    <li class="content">1</li>
    <li class="content">2</li>
    <li class="content">3</li>
    <li class="content last">4</li>
  </ul>
</div>
<div class="footer">footer</div>
    .box li.content{
      width: 24%;
      height: 300px;
      background-color: #96C02E;
      float: left;
      margin-right: 10px;
      margin-bottom: 5px;
    }
  • 方式一:
    追加带有清除浮动样式的块元素。
    在 li 标签后加一个li标签
    <li class="clr"></li>
    
    给追加的 li 赋予 清除浮动的属性
    .clr{
        clear: both;
    }
    
  • 方式二
    给浮动元素的父元素添加 overflow 属性,值可以是 hidden, auto, scroll 都能实现清除浮动
  • 方式三
    对浮动元素的父元素使用 after 伪元素清除浮动,其本质还是标签追加法
  /*  方式三 使用 :after 伪元素,对父元素追加一个空的块元素*/
    div.box::after{
      content: ""; /*after 用于定义这个伪元素的内容*/
      display: block; /*追加元素需要块元素,而伪元素默认为行内元素,故手动转块元素*/
      clear: both;
    }
/*鉴于低版本IE不支持 伪元素,出于兼容性考虑,为IE老版本加上*/
	div.box{
		*zoom:1;
	}

菜单一般使用li套a标签

此时需要将a标签填满li,可以将a转为块级元素,并设置适当的宽高即可

a {
	display: block;
	width: 100px;
	height: 30px;
	background-color: #blue;
}

外边距使用陷阱

两个相邻盒子均设置相遇方向外边距,导致较小的外边距塌陷

两盒子外边距相遇时,不会叠加两个值,而是取其中较大的一个
解决:建议外边距只设一个方向

两个嵌套盒子同时设置,上外边距(margin-top)时,此时父元素会取二者较大的外边距,而子元素没有外边距效果

解决:

  • 方式一:
    给父元素设置一个边框(可以解决,但是边框粗细不能为0,否则无效。因此会影响整体布局,不建议使用
  • 方式二:
    不使用子元素的 margin-top ,改用父元素的 padding-top 实现,注意传统盒子模型下,可能会撑大父元素,影响整体布局
  • 方式三:
    给父元素设置 overflow:hidden; 属性
  • 方式四:
    给父元素设置(固定/绝对)定位或者浮动,这三种都是利用父元素脱离文档流实现的,但是不推荐,会影响整体布局
  • 方式五:
    改变父元素显示方式,简单试了下,改成 inline-block / table …
  • 方式六:
    使用伪类元素实现,借鉴了方式五
        .test1::before{
          content: "";
          display: table;
        }
    

容易出问题的点

  • 上下外边距相遇时,会忽略较小值,直接取较大值,而不是二者之和
  • 嵌套父子盒子同时设置margin-top时,子元素无效,会计算到父元素上
  • 盒子浮动后,变成行内块的特性
  • UI上没有明显界限的多个盒子,可酌情划分
  • 盒子内图片大小,只设置一边,若同时设置宽高,可能导致图片扭曲变形
  • 不定长的导航栏或者 列表,在不确定的方向上不要设置固定的宽高,由实际内容撑开

过度和动画

过度和动画都能实现一些动态效果。
区别在于:
过度来去的效果是一样的;
而动画可以随着CSS的 附加/移除 实现慢入快出,加上class之后播放动画,移除class之后,立即消除效果。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        div {
            width: 100%;
            height: 50px;
            background: purple;
            top: -50px;
            position: fixed;
        }

        .fix {
            animation: top-move .3s linear forwards;
        }

        @keyframes top-move {
            0% {
                top: -50px
            }

            100% {
                top: 0;
            }
        }

        section {
            width: 1200px;
            height: 2000px;
            background: pink;
            overflow: hidden;
            margin: 0 auto;
        }

        aside {
            width: 100px;
            height: 100px;
            margin-top: 300px;
            background: black;
        }
    </style>
</head>

<body>
    <div></div>
    <section>
        <aside></aside>
    </section>

    <script>
        const div = document.querySelector('div')
        const aside = document.querySelector('aside')


        const divHeight = div.offsetHeight
        window.addEventListener('scroll', function (e) {
            // console.log(typeof aside.offsetTop);
            console.log(divHeight);
            const scoll_top = document.documentElement.scrollTop
            console.log(`aside.offsetTop = ${aside.offsetTop}, divHeight = ${scoll_top}`);
            if (aside.offsetTop - divHeight <= scoll_top) {
                console.log(0);
                // div.style.height = 0
                div.classList.add('fix')
            } else {
                div.classList.remove('fix')
                // console.log(divHeight);
                // div.style.visibility = 'visible'
                // div.style.height = divHeight + 'px'
            }
        })
    </script>
</body>

</html>

文字原则

盒子内不要直接写文字,基本按以下处理:

  1. 如果是单纯的文本,直接用 h1~h6(突出性文字) 或者 span(普通描述文字)
  2. 如果是单个带有点击效果的文字,用 a 标签包裹
  3. 如果是多个整齐排列的带有点击效果的文字,用 li > a 标签包裹

简写属性

font

有顺序,有可选属性

font: <font-style> <font-weight> font-size</line-height> font-family

line-height 可以为固定像素值或者纯数字(数字是相对于当前字体的倍数大小)

background

没有顺序,都是可选,至少写一个属性

background: <color> <image> <repeat> <attachment> <position>

border

盒子边框复合写法,同时定义边框大小,形状,颜色;不分顺序

border: border-width border-style border-color;

margin/padding

盒子内/外边距,第一个值从12点方向开始,一次顺时针。

  • 4个值
    依次表示上,右,下,左
# 上内边距 10px ,右内边距 20px,下内边距 30px,左内边距 40px
padding: 10px 20px 30px 40px;
  • 3个值
    依次表示上,右/左,下
# 上内边距10px 左右内边距 20px 下内边距 30px
padding: 10px 20px 30px;
  • 2个值
    依次表示 上/下,左/右
# 上下内边距10px 左右内边距 20px
padding: 10px 20px;
  • 1个值
    上下左右内边距都是一个值
上下左右内边距都是 10px
padding: 10px;

2d转换简写

先后顺序为:位移 → 旋转 → 缩放

transform: translate() rotate() scale() 

由于位移会影响坐标,需要仔细考虑先后顺序。

CSS 有很多表示状态的伪类选择器,平时虽然用得可能没那么多,但要知道有

  • :disabled :禁用时的样式(常用于各种表单组件)
  • :checked:选中时的样式(常用于单选/复选框)
  • ::placeholder:定义placeholder 默认提示内容的样式(这个选择器有两个 ::)
  • :link
  • :visited
  • :hover
  • :active
    … 其他还有很多,具体可以查看

JS

鼠标进入离开事件与:hover的区别

鼠标经过,离开 事件注意和伪类选择器 :hover区分开:
经过和离开是独立的事件,分别有不同的动作,都有结果,结束后效果会保持。
而**:hover仅仅悬浮期间有效,一旦离开恢复元素原有样式**。

JS操作样式:推荐使用 classList 的方式,更便于维护。

mouseover mouseout VS mouseenter mouseleave

VS前后两种事件,业务含义一样,都是鼠标进入,离开的事件。
但是 mouseover mouseout 会触发捕获冒泡,在页面结构较为复杂时,随着鼠标的移动会有很多事件被触发,可能带来性能问题

因此,实际现在更推荐使用 mouseenter mouseleave 这两个事件,此二者不会触发捕获和冒泡
详情见这里

JS事件流

事件流的传递并不依赖目标元素是否绑定了对应事件。

比如:
子元素没有绑定单击事件,父元素绑定了单击事件。
此时,单击了子元素,由于事件冒泡的原因,该事件依然冒泡给了父元素。
所以,结果就是:单击没有绑定事件的子元素,父元素的事件被触发。

事件委托

事件委托:常用于给一个列表批量绑定事件;将事件绑定给父元素,然后利用事件冒泡,由子元素来触发。

HTML标签自定义属性

HTML规范中,建议自定义属性统一命名规范:以 data- 开头;
JS的DOM对象中,统计将自定义属性封装到 dataset 属性中

const value = dom.dataset.key

JS获取页面特殊标签

通过一般获取方式document.querySelector 都能获取到;
对于一些特殊的标签,有更简洁的方式获取其dom对象;

  • html标签:document.documentElement
  • head标签:document.head
  • body标签:document.body

事件循环

JS是单线程,对于异步操作会进入一个队列;待同步代码执行完毕;
再去任务队列拉取异步任务执行。
执行一个再去拉取,一直循环。
定时器和延迟器记得清除

JS获取单选复选框下拉框选中的值

  • 单选/复选
const gender = document.querySelector('input[name="gender"]:checked')

gender.value
const province = document.querySelector('select[name="province"]')

province.value

JS中需要写分号的场景

  1. 立即执行函数
(function(){
	// code
})();
  1. 直接以 [] 形式的数组开头的语句不是第一行时
const a = 1
// 直接以 [] 形式调用数组方法
[1,2].xxx 

// 数组解构时
const arr = [1,2,3];
[first, second, third] = arr

非空运算符

为了防止对象为空时链式调用报错。可以使用 ?. 运算符,当前面的对象为空时,就不会执行后续调用。

obj1?.key1?.key2

obj?.fun1()?.func2()

前端预览图片

使用 URL.createObjectURL(file对象) 得到本地预览url

img.src = URL.createObjectURL(file对象)

JS url编码

escape 和 unescape

用于对普通字符串编解码

encodeURI 和 decodeURI

对整个url进行编码,忽略在url 有特殊含义的字符

encodeURIComponent 和 decodeURIComponent

同样是对整个url进行编码,对url特殊字符同样进行编码

dayjs实现倒计时

  1. date1.diff(date2, ‘second’) 计算得到两个时间相差的秒数
  2. dayjs.unix(秒数) .format(‘mm份ss秒’) 得到格式化后的字符串

请求后端图形验证码方案

  • 后端以Base64形式返回,前端img标签直接以 src 接收data:image/png;base64,图片的Base64编码值

  • 后端以 ContentType(“image/jpeg”) 或其他html支持的图片格式,以输出流的形式返回

    out = response.getOutputStream();
    ImageIO.write(bi, "jpg", out);
    out.flush();
    

前端直接将返回值,写入src属性

Vue

Vue事件函数同时接收渲染的参数和事件的参数

vue事件在触发时,有的参数是外部传入,有的是直接取渲染时的属性
如果要同时取这两者需要换一种写法。
item 是渲染时的对象,num则是事件触发时外部传入的参数(直接写的事件函数只能接收num一个参数

@input="(num) => fn1(item, num)"

Vue自定义组件监听原生事件

在自定义组件上,默认是无法监听原生事件,Vue会认为这个事件是子组件内部的自定义事件。
想要监听原生事件需要加上一个指令修饰符:.native

<my-item @click.native="handleClick">
	
</my-item>

封装 async await 通用Promise异常处理

切记一点,这个函数处理的前提是拿到了Promise结果,如果在目标函数执行期间出现异常,未能拿到Promise对象是无法处理的,依然需要在自行 try - catch

export const asyncAwait = (promise) => {
  try {
    return promise
      .then(res => ({ res, undefined }))
      .catch(err => ({ undefined, err }))
  } catch (err) {
    return { undefined, err }
  }
}
  • 使用
const awaitRes = await asyncAwait(fn())
if (awaitRes.res) {
	// 业务逻辑
}
  • 无法处理的示例
const fn = () => {
	// code ...,直接抛出异常
	throw Error('系统异常')
}

uniapp

Vue 和 uniapp 部分生命周期执行顺序

Vueuniapp
setup
beforeCreate
"onLoad(非根组件触发)
created
beforeMount
"onLaunch(只在根组件触发)
‘’onReady(非根组件触发)
‘’onShow
mounted

并且 uniapp 会不断检测当前应用是否得到焦点:分别触发 :onShowonHide 生命周期函数

uniapp 中同一个组件内,相同生命周期函数,可能会被后面的覆盖

uniapp 回调函数this指向

  • 箭头函数
    指向外层 this,在Vue2中可直接使用this 访问 data数据
  • 变量形式或普通函数形式
    指向当前回调函数

综上,要在回调函数中访问 data 中的数据,要么回调函数使用箭头函数形式,要么在当前函数内将所需的data数据本地化,或者直接将 this 重新指向本地变量。

示例:

popMenu(){
	const arr = this.arr
	// 或者直接将this指向本地变量
	// const that = this
	uni.showActionSheet({
		title: '测试菜单',
		alertText: '提示文字',
		itemList: this.arr,
		// 普通函数,通过本地的 arr变量访问
		// success:function(res){
		// 	console.log(arr, this)
		// console.log(that.arr, this)
		// }
		// 普通函数,通过本地的 arr变量访问
		success(res) {
			console.log(arr, this)
		}
		// 箭头函数直接访问 data中数据
		// success: (res) => {
		// 	console.log(this.arr)
		// }
	})
}

uniapp绑定数组,数组发生增减元素,不触发渲染

如果直接在JS中增减数组中的元素,未触发页面实时渲染;需要重新个数组赋值。

uniapp微信小程序页面进入未渲染数据

进入首页,加载数据失败;
开发者模拟环境没问题;真机出现问题,无法加载出数据。

开发单纯的Vue应用通常将页面请求放到 :created或者mounted 生命周期函数中。
经过测试,uniapp 编译成微信小程序:这个请求需要放到 mounted 或者 onReady 生命周期函数中。
但是官方文档中,推荐网络请求放到 onLoad 中。。。后续再看看

uniapp 内置的scss 变量

uniapp css变量 文档

CSS 变量描述App小程序H5
–status-bar-height系统状态栏高度系统状态栏高度、nvue 注意见下25px0
–window-top内容区域距离顶部的距离00NavigationBar 的高度
–window-bottom内容区域距离底部的距离00TabBar 的高度

由于小程序自带一个顶部区域;实际的显示区域是从导航条下面开始计算的,而H5中则是以页面顶部开始计算的。
因此,在需要使用顶部定位时,要使用 uniapp 内置的一个变量 –window-top;同样对于底部也是一样,需使用 –window-bottom 这个变量

  • 在scss 中使用变量原生的语法就是直接使用变量名替换即可
  1. 定义变量
$highlight-color: #F90;
  1. 使用变量
.selected {
  border: 1px solid $highlight-color;
}
  • 使用uniapp 内置的scss 变量,使用 var(变量名) 的方式
height: var(--status-bar-height);

swagger3 响应体为空的问题

外层泛型不加 @Scheme

Mybatis一对多问题

通常会使用 collectionassociation 标签实现多表关联查询。
基本语法:

< collection property="实体类中自定义字段名(子查询中使用这个名称)" column="主查询结果集中的关联字段" ofType="多中的类型" select="子查询 select">< /collection>

通常 column 字段都是传递查询结果集中的一个字段到子查询中。
如果要传递多个字段到子查询,可以采用以下方式。

< collection property="实体类中自定义字段名" column="{id=id, userName=user_name}" ofType="多中的类型" select="子查询 select">< /collection>

userName:传入子查询中字段名
user_name:主查询中结果集中的字段名

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值