面试官常问到的面试题 (总结)

134 阅读21分钟

vue 当中经常问到的

. 对seo搜索优化的了解
1. 什么是搜索引擎
搜索引擎就是从互联网上采集信息,并采用一定的规则对信息进行分类和索引,在用户需要的时候提供查询,下图是谷歌搜索引擎的工作原理大致图(详细的工作原理属于商业机密)
2. 搜索引擎优化:
SEO全称Search(搜索) Engine(引擎) Optimization(优化)的要点就是了解搜索引擎采集和分析信息的规则,对网站进行一定的调整,使网站更好的被搜索引擎收录并展现出来,最好的展现效果是在首页出现,这会给你带来很高的流量。
. img 的 titlelet 的区别
title是鼠标在图片上悬停的时候会有提示
image.png
alt 是在图片加载不出来或者错的是时候显示

image.png

. src 和 href 的区别

href 是超文本引用 它指向一些网络资源,建立和当前元素或者说是当前文档的链接关系。在加载它的时候,不会停止对当前文档的处理,浏览器会继续往下执行。通常在a、link等标签中使用

src表示的是对资源的引用,它执行的内容会嵌入到当前标签所在的位置 当浏览器解析到src的时候会停下了,直到src解析完之后才会往下执行
简单来说就是当浏览器加载到 href 的时候不会等到href解析完 但是解析src的时候浏览器会等到src加载完之后才会往下执行

. 重绘和回流

一.首先要了解一下浏览器渲染机制

  1. 浏览器采用的是流式布局
  2. 首先浏览器会将HTML解析成DOM元素,把CSS解析成CSSOM,然后DOM和CSSOM结合会形成render tree(也就是DOM树)
  3. 有了render tree之后,我们知道了节点样式,然后浏览器会计算节点的位置,然后节点会把节点绘制到页面上

二.回流

当我们render tree中的一些元素的节后或者是尺寸发生改变的时候,浏览器重新渲染的部分或者是重新渲染全部文档的过程就叫做回流

导致回流的的操作:

  • 首页渲染的时候
  • 内容发生改变的时候
  • 浏览器页面发生改变的时候
  • 添加或删除DOM节点的时候

三.重绘

当页面中元素样式发生改变而且不能影响他在页面中的位置,浏览器会将新的样式赋值给元素的过程叫做重绘

导致重绘的操作:

  • background
  • visibility

小小总结: 回流一定会引起重绘,但是重绘不一定会引起回流

三. 性能影响

回流的性能消耗会比重绘大

. new操作符具体干了什么

  1. 创建了一个空的对象
  2. 将空对象的原型,指向于构造函数的原型
  3. 改变this指向
  4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。

. ajax的原理 浏览器利用XMLHttpRequest对象向服务器获取数据

  1. 创建对象XMLHttpRequest请求对象实例
  2. 注册成功回调函数
  3. 设置请求参数,建立服务器连接
  4. 向服务器发送请求

. 常见的设计者模式有哪些
1.单例模式:
单例模式就是保证一个类只有一个实例,实现方法就是一般是判断是否有这个实例,有的话就直接返回,如果没有的话就创建了这个实例再返回

       var mySingleton = {
        property: 'something',
        property2: 'something else',
            method1: function() {
                console.log("hello world");
            }
        }
        var s1 = mySingleton;
        var s2 = mySingleton;
        console.log(s1 === s2); // true

2.观察者模式:
观察者模式简单理理解为:当一个对象发生改变需要同时改变其他对象的时候,并且不知道需要改变多少个对象的时候就可以用到观察者模式

. 对promise的了解
Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。 promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态) ;状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

then的使用

    //链式调用
    let p = new Promise((resolve, reject) => {
            //做一些异步操作
            setTimeout(() => {
                console.log('执行完成');
                resolve('我是成功!!');
            }, 2000);
        });

        p.then((data) => {
            console.log(data);
        })
        .then((resolve) => {
            console.log(1);
        })
        .then((resolve) => {
            console.log(2);
        });

catch的使用

     let p = new Promise((resolve, reject) => {
            reject('我是失败!!');
        });

        p.catch((err) => {
                console.log('rejected',err);
        });

race的用法:谁跑的快,以谁为准执行回调

  // 执行快的
    function requestfast(){
        var p = new Promise((resolve, reject) => {
            resolve('我执行的快')
        });
        return p;
    }
    // 执行的慢的
    function requestslow(){
        var p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('我执行的慢');
            }, 5000);
        });
        return p;
    }
    Promise.race([requestfast(), requestslow()]).then((data) =>{
        console.log(data);
    }).catch((err) => {
        console.log(err);
    });

promise.all接收一个数组为参数,当数组的所有Promise都为resolve的状态时,Promise.all()才会成功;若有一个失败,都会被认为是失败的。

     var p1 = Promise.resolve('a');
     var p2 = Promise.resolve('b');
     var p3 = Promise.resolve('c');
    Promise.all([p1,p2,p3]).then(function(value) {
        console.log(value);
    })
    

. js数据类型有哪些

在ES5的时候我们认知的数据类型确实有6种: Number/String/Boolean/undefined/Object/Null

  • 在Es6中有新增了一种Symol。这种数据类型的对象永不相等、及创建的时候传入相同的值,可以解决命名冲突的问题,作为标记
  • 还有一种在谷歌中出现过一种bigint。是指安全存贮操作大整除出现的
  • 准确的来说一共有8种: 基本数据类型: String、Number、Boolean、Null、Undefined、Symbol、BigInt
    复杂数据类型(引用数据类型): Object是个大类【function函数、array数组、date日期...等都属于Object】

. js的内存存储方式

  • 基本数据类型
  1. 声明一个变量a的时候,会在栈里面开辟出一块新的内存空间,用来存放这个变量a的值
  2. 当变量 a 储存的数值发生改变时,栈区里对应的那块内存里存的数据也会发生改变
  3. 再声明一个变量b,并把变量a赋值给变量b,此时会在栈内开辟一个新空间用来储存变量b。
  4. 这时变量a和变量b对应栈内存中两个空间,修改其中一个不会影响到另一个

image.png

  • 复杂数据类型
  1. 声明一个对象var obj1 = {name: ‘sheng’}, 此时会在堆中开辟一块空间存放obj1值{name: ‘sheng’}
  2. 在栈中开辟一个空间存放指向obj1值的指针,obj1通过这个指针可以拿到堆中的值
  3. 如果将obj1这个对象赋值给obj2时,此时其实赋值给obj2是栈中的指针,
  4. 那么obj1和obj2通过相同的指针指向是同一个值,修改其中一个对象的值,会影响到另一个对象。
  5. 如果对obj1重新赋值的话,那么这个对象会堆中的另一块区域,不会在与obj2共享同一块区域。

image.png

十一. js里如何判断是不是一个数组

  1. 用法Array.isArray()

Array.isArray() 用于确定传递的值是否是一个[Array], 返回布尔值 true;否则它返回 false。

    let arr = [];
    let obj = {}
    console.log(Array.isArray(arr)); // true
    console.log(Array.isArray(obj)); // false

2.用法: arr.constructor === Array

Object的每个实例都有构造函数 constructor,用于保存着用于创建当前对象的函数

   let arr = [];
   let obj = {}
   console.log(arr.constructor === Array); // true
   console.log(obj.constructor === Array); // false
  1. instanceof 判断

用法: arr instanceof Array

instanceof 主要是用来判断某个实例是否属于某个对象

    let arr = [];
    let obj = {}
    console.log(arr instanceof Array);//true
    console.log(obj instanceof Array);//false
  1. instanceof 判断

用法: Array.prototype.isPrototypeOf(arr)

Array.prototype属性表示 Array 构造函数的原型
isPrototypeof()可以用于测试一个对象是否存在于另一个对象的原型链上

    let arr = [];
    let obj = {}
    console.log(Array.prototype.isPrototypeOf(arr)); // true
    console.log(Array.prototype.isPrototypeOf(obj)); // false

十二. map 和 forEach 的区别

  • forEach() 没有返回值
    var array = [10,34,57,43,76];  
    var res = array.forEach(function (item,index,input) {  
       input[index] = item*10;  
    })  
    console.log(res);//--> undefined;  
    console.log(array);//--> 通过数组索引改变了原数组;
  • **map()**返回一个新的数组 有返回值,可以return出来
    var array = [10,34,57,43,76];
    var res = array.map(function (item,index,input) {
      return item*10;  
   })
   console.log(res);  [100, 340, 570, 430, 760]
   console.log(array);不变 [10, 34, 57, 43, 76]

十三. vue2双向绑定的原理

vue 在实例化的时候,使用 Object.definePropery() 方法,对 data 进行 getter 和 setter 的处理。在组件渲染时,若用到 data 里的某个数据,这个数据就会被依赖收集进 watcher 里。当数据更新,如果这个数据在 watcher 里,就会收到通知并更新,否则不会更新——vue 采用“数据劫持”+“观察者模式”相结合的方式实现了双向绑定——vue 的响应式原理。

十四. 数据去重的方法有哪些

  1. new Set() 利用了Set结构不能接收重复数据的特点
    var arr = [1,2,3,4,5,6,7,8,9,1,2,3];
    console.log(new Set(arr));
    console.log(arr);   
    function noRepeat(arr){
         var newArr = [...new Set(arr)]; 
         return newArr
    }
    var arr2 = noRepeat(arr)
    console.log(arr2); 
  1. filter:过滤掉数组中不满足条件的值,返回一个新数组 不改变原数组的值
    var arr = [1,2,3,4,5,6,7,8,9,1,2,3];
    console.log(arr)
    let newArr = arr.filter((item,index)=>{
        console.log(arr.indexOf(item));
        return arr.indexOf(item)===index
    })
    console.log(newArr);
  1. 利用indeof
     var arr = [1,2,3,4,5,6,7,8,9,1,2,3];
    function noRepeat(arr){
        let newArr = []
       for (let i = 0; i < arr.length; i++) {
           if(newArr.indexOf(arr[i])===-1){
            newArr.push(arr[i])
           }
       }
       return newArr   
    }
    console.log(noRepeat(arr));

十五. 防抖和节流 防抖,是在固定得时间内没有触发,然后再固定事件结束后进行触发,如果实在固定得时间内触发了事件,会延长相应的固定时间再触发
应用场景

  • 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
    function fang(fn, delay = 1000) {
        let timer;
            return function(...ages) {
                if (timer) {
                    clearTimeout(timer)
                }
                timer = setTimeout(() => {
                    fn.apply(this, ages)
                }, delay);
            }
        }
        //引入jQuery
        $("input").on('input', fang(() => {
            console.log($('input').val());
        }))

节流,是无论在固定得时间内是否触发,都会按照固定时间规律的去触发

     function jie(fn, timer = 1000) {
            let prev = 0;
            return function(...ages) {
                let now = new Date()
                if (now - prev > timer) {
                    fn.apply(this, ages)
                    prev = now
                }
            }
        }
        //引入jQuery
        $("input").on('input', jie(() => {
            console.log($('input').val());
        }))

十六. apply、call、bind 的区别

call,apply,bind的主要作用是改变this指向的,但是在使用上略有不同

call()
call后面传递的参数是以逗号的形式分开

    function Product(name, price) {
      this.name = name;
      this.price = price;
    }
    function Food(name, price) {
      Product.call(this, name, price);
      this.category = 'food';
    }
    console.log(new Food('cheese', 5).name);

apply()
apply传递的参数是数组形式【Apply是以A开头的】

    var num = [1,3,12,11,54];
    Math.max.apply(window,num);  //使用null 也可以第一个参数
    console.log(Math.max.apply(null,num));

bind()

        function title(){
            setInterval(function(){
                console.log('hello world');
            },1000);
        }
        title.bind(this) 
        title.bind(this)()

十七. this指向

this是什么

this是当前执行上下文(globalfunctioneval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。

大多数情况下,this会出现在函数中,而在全局作用域中也有this

全局作用域中的this

上面说到在全局作用域中我们也是可以直接打印this的。

浏览器环境:
console.log(this); // window
Node环境:
console.log(this); // {}
console.log(window); // 在node会报错, no defined
复制代码

从这可以看出this在不同的环境上是不一样的。

this的作用

JavaScript中我们在一个对象中想给本身的一个属性赋值往往会使用this.[attr]=xx,这里可以看出this指向的是当前test对象,当没有this时你也可以使用[object name].[attr]的语法来操作属性,但这样子会有个弊端,也就是说当你的对象中里面有很多个方法,而这些方法中很多出现[object name].[attr]语法,那么后续修改对象名称,方法里对于对象名称也需要修改,很不方便。这也即是this的作用。

十八. 判断js的数据类型

1.typeof

    typeof 1           //number
    typeof 'a'         //string
    typeof true        //boolean
    typeof undefined   //undefined
    typeof null        //object
    typeof {}          //object
    typeof [1,2,3]     //object
    function Fn(){}
    typeof new Fn()    //object
    typeof new Array() //object

2.根据constructor判断

    console.log('数据类型判断 -  constructor');
    let num = 23;
    let date = new Date();
    let str = "biu~";
    let reg = new RegExp();
    let bool = true;
    let fn = function () {
      console.log(886);
    };
    let udf = undefined;
    let nul = null;
    let array = [1, 2, 3];
    console.log(num.constructor); // [Function: Number]
    console.log(date.constructor); // [Function: Date]
    console.log(str.constructor); // [Function: String]
    console.log(bool.constructor); // [Function: Boolean]
    console.log(fn.constructor); // [Function: Function]
    console.log(reg.constructor); // [Function: RegExp]
    console.log(array.constructor); // [Function: Array]
 

十九. 时间循环机制(eventloop)的理解

eventloop是js的一个地城运行原理,js是单线程的,到那时也有一些耗时的任务,会影响执行效率,代码都在主线程里面执行,但是遇到ajax请求,setTimeout定时器的时候,会单独开启一部线程,异步线程耗时之后回推入异步队列中等待执行,然后当主线程执行完毕之后,会到异步队列中取出到主线程执行,然后再去异步队列中取出第二个,这个来回去的过程就叫做事件循环

二十. 常见的跨域方式 里面有 (跨域请求 - 掘金 (juejin.cn)) 二十一. 存储方式(浏览器)

浏览器常用存储数据的方式有cookies、session storage、local storage、

cookies

  • 存储大小

    • 4KB,纯文本格式,超过被忽略
    • 所以很少被用于存储客户端数据
  • 存储时间

    • 可以设置过期时间,expires选项

    • 会话期cookie浏览器关闭自动清除

    • 持久性cookie设置过期时间,到期后清除

    //获取cookie
    const allCookies = document.cookie;
  • 删除cookies

    • 设置它的expires属性为一个过去的日期
    document.cookie = 'test1=hello;expires=Thu, 01-Jan-1970 00:00:01 GMT';

sessionStorag

  • 存储大小

    • 2.5~10M
  • 存储时间

    • 页面会话期可用,关闭浏览器消失

    • 页面刷新和恢复也可用

    • 打开多个相同url的tab页面,会创建各自的session,即不可相互访问

    • 使用location.href或者window.open来打开另一个同域页面 是可以访问的

      • 先操作session再打开才会有
    • 清除缓存也会消失

  • 设置sessionStorage

    • 三种方法都可以
    window.sessionStorage['name'] = 'yangfeng';  
    window.sessionStorage.age = 18; 
    window.sessionStorage.setItem('key','value')
  • 获取sessionStorage
    sessionStorage.getItem("name"); 
    sessionStorage.name
  • 删除sessionStorage
    // 删除某个sessionStorage  
    sessionStorage.removeItem('key');  
    delete sessionStorage.name; // 清除所以数据   
    sessionStorage.clear();

localStorage

  • 存储大小

    • 2.5~10M
  • 存储时间

    • 永久保存
    • 手动清除或者清除缓存
  • 不可以和服务器对话

  • 可以保存任意内容

    window.addEventListener('storage',   
    function(e) { console.log('---',e) });

二十二. 浏览器的缓存策略
强缓存
到底什么是强缓存?强在哪?其实强是强制的意思。当浏览器去请求某个文件的时候,服务端就在respone header里面对该文件做了缓存配置。缓存的时间、缓存类型都由服务端控制,具体表现为:
respone header 的cache-control,常见的设置是max-age public private no-cache no-store等

协商缓存
上面说到的强缓存就是给资源设置个过期时间,客户端每次请求资源时都会看是否过期;只有在过期才会去询问服务器。所以,强缓存就是为了给客户端自给自足用的。而当某天,客户端请求该资源时发现其过期了,这是就会去请求服务器了,而这时候去请求服务器的这过程就可以设置协商缓存。这时候,协商缓存就是需要客户端和服务器两端进行交互的。

二十三. vue2的声明周期 里面有vue2 vue3的生命周期和使用

Vue3.2中setup语法糖的基本使用 - 掘金 (juejin.cn)

二十四. http的常见的状态码

image.png

image.png

  • 14种常用的HTTP状态码列表
状态码状态码英文名称中文描述
200OK请求成功。一般用于GET与POST请求
204No Content无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
206Partial Content是对资源某一部分的请求,服务器成功处理了部分GET请求,响应报文中包含由Content-Range指定范围的实体内容。
301Moved Permanently永久性重定向。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302Found临时性重定向。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303See Other查看其它地址。与302类似。使用GET请求查看
304Not Modified未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
307Temporary Redirect临时重定向。与302类似。使用GET请求重定向,会按照浏览器标准,不会从POST变成GET。
400Bad Request客户端请求报文中存在语法错误,服务器无法理解。浏览器会像200 OK一样对待该状态吗
401Unauthorized请求要求用户的身份认证,通过HTTP认证(BASIC认证,DIGEST认证)的认证信息,若之前已进行过一次请求,则表示用户认证失败
402Payment Required保留,将来使用
403Forbidden服务器理解请求客户端的请求,但是拒绝执行此请求
404Not Found服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面。也可以在服务器拒绝请求且不想说明理由时使用
500Internal Server Error服务器内部错误,无法完成请求,也可能是web应用存在bug或某些临时故障
501Not Implemented服务器不支持请求的功能,无法完成请求
503Service Unavailable由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中

二十五. es6新增的语法

ES6新增的有很多但是我经常用到的也就是这些!
let/const,箭头函数,模板字符串,解构赋值,模块的导入(import)和导出(export default/export),Promise

二十六. vue父子传值
Vue3.2中setup语法糖的基本使用 - 掘金 (juejin.cn)
二十九. computed和watch的区别
computed支持缓存,相依赖的数据发生改变才会重新计算;watch不支持缓存,只要监听的数据变化就会触发相应操作

computed不支持异步,当computed内有异步操作时是无法监听数据变化的;watch支持异步操作

computed属性的属性值是一函数,函数返回值为属性的属性值,computed中每个属性都可以设置set与get方法。watch监听的数据必须是data中声明过或父组件传递过来的props中的数据,当数据变化时,触发监听器

以上是在以往当中vue经常被问到的

css 当中经常问到的

. 行内元素和块级元素

块级元素

块级元素说明
div最经典的块元素
p表示段落
h1 - h6表示1-6级标题(默认加粗)
br表示换行
ol无需列表
ul有序列表

行内元素

行内元素说明
a超链接
sapn常用在行内
strong加粗(强调)
b加粗(不强调)
em倾斜(强调)
i倾斜(不强调)
img图片
input输入框
select下拉框

. 媒体查询的使用方式

1、媒体查询语法

  • 使用@media查询,可以针对不同的媒体类型定义不同的样式
  • @media可以针对不同的屏幕尺寸设置不同的样式
  • 当年充值浏览器大小的过程中,页面也会更具有浏览器的宽度和高度重新渲染页面

语法:

@media mediatype and|not|only (media feature) {
    css-code;
}
复制代码
  • 用@media开头
  • mediatype 媒体类型
  • 关键字and not only
  • media feature 媒体特性 必须有小括号包含

语法规范

2、mediatype查询类型

将不同的终端设备划分成不同的类型,称为媒体类型

说明
all用于所有设备
print用于打印机和打印预览
scress用于电脑、平板、智能手机等屏幕

3、关键词

关键词将媒体类型或多个媒体特性连接到一起作为媒体查询的条件

  • and:可以将多个媒体特性连接到一起,相当于“且”的意思
  • not:排除某个媒体类型,相当于“非”的意思,可以省略
  • only:指定某个特定的媒体类型,可以省略

4、媒体特性

说明
width定义输出设备中页面可见区域的宽度
min-width定义输出设备中页面最小可见区域宽度
min-width定义输出设备中页面最大可见区域宽度
    /* 一、 小于等于700px 页面颜色为此 */
    @media screen and (max-width:539px) {
        body {
            background-color: aquamarine;
        }
    }
    /* 二、701~900px 页面颜色改为 红色 */
    @media screen and (min-width:540px) {
        body {
            background-color: red;
        }
    }
    /* 三、大于等于970时,页面颜色都为绿色 */
    @media screen and (min-width:970px) {
        body {
            background-color: green;
        }
    }

. css让元素看不到的方法

1. color alpha 透明度

可以将元素的color、background-color 和 border-color 等属性设置为rgba(0,0,0,0),这样就会使元素完全透明:

div {
   color: rgba(0,0,0,0);
   background-color: rgba(0,0,0,0);
}

2. color alpha 透明度

可以将元素的color、background-color 和 border-color 等属性设置为rgba(0,0,0,0),这样就会使元素完全透明:

div {
	color: rgba(0,0,0,0);
  background-color: rgba(0,0,0,0);
}

5. visibility: hidden

visibility 属性可以设置为 visible 或 hidden 来显示和隐藏元素。

div {
	visibility: hidden;
}

6. display: none

display 可能是最常用的元素隐藏方法; 。当其值为 none 时元素就隐藏了。被隐藏的元素不会在页面中占据位置,也不会响应绑定的监听事件。

div {
      display: none;
 }

7. z-index

可以通过将元素的 z-index 属性设置为负值,以实现元素的隐藏。这实际上就是将元素放在了我们看不到的层。

div {
  z-index: -1;
}

. 标准盒子模型和怪异盒子模型

1.标准盒模型采用的W3C标准,盒子的content内容部分由width宽度和height高度决定,添加padding内边距或border外边框后,宽高都会进行相应增长;

2.怪异盒模型也称为IE盒模型,是IE浏览器设计元素时遵循的规则。怪异盒模型的宽高在div盒子初次设置时就已经规定,添加padding或者border,会从中减少content内容的占据区域,来为padding和border制造空间,宽高不会相对应的进行增长。

. 如何清除浮动

清除浮动的三个常用方法:

  1. 给浮动元素的父级元素设置overflow:hidden;
  2. 在浮动元素的同级下添加一个空标签,并且设置clear:both;
  3. 浮动元素的父级元素使用::after{clear:both;content:'';display:block;}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>浮动以及清除浮动</title>
</head>
<style>
	*{
		list-style: none;
		padding:0;
		margin: 0;
	}
	.wrap{
		background-color: red;
		margin-bottom: 2em;
		/*方法一:给父元素设置overflow:hidden;*/
		overflow: hidden;
	}
	.FirstUl li{
		float: left;
	}
 
	.Second{
		background-color: red;
		margin-bottom: 2em;
	}
	.SecondUl li{
		float:left;
	}
	.test{
		/*方法二:在浮动元素的同级添加一个空标签,设置为clear:both;*/
		clear: both;
	}
 
	.Third{
		background-color: red;
	}
	.ThirdUl li{
		float: left;
	}
	/*方法三:给浮动元素的父元素使用::after{};*/
	.ThirdUl::after{
		content: '';
		display: block;
		clear: both;
	}
</style>
<body>
	<div class="wrap">
		<ul class="FirstUl">
			<li>测试</li>
			<li>测试</li>
			<li>测试</li>
		</ul>
	</div>
 
	<div class="Second">
		<ul class="SecondUl">
			<li>测试</li>
			<li>测试</li>
			<li>测试</li>
			<div class="test"></div>
		</ul>
	</div>
 
	<div class="Third">
		<ul class="ThirdUl">
			<li>测试</li>
			<li>测试</li>
			<li>测试</li>
		</ul>
	</div>
 
</body>
</html>

. rem和em的区别

  • px是固定像素,一旦设置了就无法因为适应页面而改变。
  • em是rem相对于px更具有灵活性,他们是相对于长度单位的变化而变化,更适应于响应式布局

. 实现一个div上下左右居中三种方法
绝对居中

.xx_div {
    position: absolute;
    /* left, right, bottom, top要和position一起使用,margin-*不用 */
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}
 

浮动居中 float只有left和right,没有center。 可以如下设置居中

.xx_div {
    margin-left: auto;
    margin-right: auto;
}

对于内联元素,直接 text-align: center; 即可。当然对于块状元素,也可以先display: inline-block然后text-align:center