[前端面试套餐css+js+vue+es6]第八天

css:如何实现两栏布局,右侧自适应?三栏布局中间自适应呢?

在日常布局中,无论是两栏布局还是三栏布局,使用的频率都非常高

两栏布局

两栏布局实现效果就是讲页面分割成左右宽度不等的两列,宽度较小的列设置iwei固定宽度,剩余宽度由另一列撑满(列较小的为次要布局容器,宽度较大的为主要布局)

BFC+float

  • 使用float左浮左边栏
  • 右边模块使用margin-left撑出内容块做内容展示
  • 为父级元素添加BFC,防止下方元素飞到上方内容
<style>
    .box{
        overflow: hidden; 添加BFC
    }
    .left {
        float: left;
        width: 200px;
        background-color: gray;
        height: 400px;
    }
    .right {
        margin-left: 210px;
        background-color: lightgray;
        height: 200px;
    }
</style>
<div class="box">
    <div class="left">左边</div>
    <div class="right">右边</div>
</div>

flex弹性布局

<!--
 * @Author: 41
 * @Date: 2021-12-07 09:37:47
 * @LastEditors: 41
 * @LastEditTime: 2021-12-07 09:40:35
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            display: flex;
            /* align-items: flex-start */
        }
        .left{
            width: 200px;
            height: 500px;
            background-color: gray;
        }
        .right{
            flex: 1;
            margin-left: 10px;
            background-color: black;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="left">左边</div>
        <div class="right">右边</div>
    </div>
</body>
</html>

flex可以说是最好的方案了,代码少,使用简单

注意的是,flex容器的一个默认属性值:align-items: stretch;

这个属性导致了列等高的效果。为了让两个盒子高度自动,需要设置: align-items: flex-start;

注意,这里的 flex:1;=== flex-grow:1;flex-shrink:1;flex-basis:0%

三栏布局

三栏布局按照左中右的顺序进行排序,通常中间列最宽,左右两列次之

实现三栏布局中间自适应的布局方式有:

  • 两边使用float,中间使用margin
  • 两边使用absolute,中间使用margin
  • 两边使用float和负margin
  • display:table实现
  • flex实现
  • grid网格布局

两边使用float,中间使用margin

  • 两边固定宽度,中间宽度自适应
  • 利用中间元素的margin值控制两边的间距
  • 宽度小于左右部分宽度之和时,右侧部分会被挤下去
<!--
 * @Author: 41
 * @Date: 2021-12-07 09:57:56
 * @LastEditors: 41
 * @LastEditTime: 2021-12-07 10:14:10
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .wrap {
            background: #eee;
            overflow: hidden; 
            padding: 20px;
            height: 200px;
        }
        .left {
            width: 200px;
            height: 200px;
            float: left;
            background: coral;
        }
        .right {
            width: 120px;
            height: 200px;
            float: right;
            background: lightblue;
        }
        .middle {
            margin-left: 220px;
            height: 200px;
            background: lightpink;
            margin-right: 140px;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="left">左侧</div>
        <div class="right">右侧</div>
        <div class="middle">中间</div>
    </div>
</body>
</html>

缺陷:

  • 主题内容最后加载
  • 右边在主题内容之前,如果是响应式设计,不能简单的换行展示

两边使用absolute,中间使用margin

基于绝对定位的三栏布局:注意绝对定位的元素脱离文档流,相对于最近的已经定位的祖先元素进行定位。无需考虑html中结构的顺序。

  • 左右两边使用绝对定位,固定在两侧
  • 中间占满一行,但通过margin和左右两边留出10px的间隔
<!--
 * @Author: 41
 * @Date: 2021-12-07 10:33:42
 * @LastEditors: 41
 * @LastEditTime: 2021-12-07 10:43:28
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .container {
            position: relative;
        }
        .left,
        .right,
        .main {
            height: 200px;
            line-height: 200px;
            text-align: center;
        }
        .left {
            position: absolute;
            top: 0;
            left: 0;
            width: 100px;
            background: green;
        }
        .right {
            position: absolute;
            top: 0;
            right: 0;
            width: 100px;
            background: green;
        }
        .main {
            margin: 0 110px;
            background: black;
            color: white;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="left">左边固定宽度</div>
        <div class="right">右边固定宽度</div>
        <div class="main">中间自适应</div>
    </div>
</body>
</html>

两边使用float和负margin

实现过程:

  • 中间使用双层标签,外层浮动,以便左中右能在同一行展示
  • 左边通过使用负margin-left:-100%,相当于中间的宽度,所以向上偏移到左侧
  • 右边通过使用负margin-left:-100px,相当于自身宽度,所以向上偏移到最右侧

缺点:

  • 增加了.main-wrapper一层,结构变复杂
  • 使用负margin,调试相对麻烦
<!--
 * @Author: 41
 * @Date: 2021-12-07 10:51:28
 * @LastEditors: 41
 * @LastEditTime: 2021-12-07 10:58:40
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .left,
        .right,
        .main {
            height: 200px;
            line-height: 200px;
            text-align: center;
        }

        .main-wrapper {
            float: left;
            width: 100%;
        }

        .main {
            margin: 0 110px;
            background: black;
            color: white;
        }

        .left,
        .right {
            float: left;
            width: 100px;
            margin-left: -100%;
            background: green;
        }

        .right {
            margin-left: -100px; /* 同自身宽度 */
        }    
    </style>
</head>
<body>
    <div class="main-wrapper">
        <div class="main">中间自适应</div>
    </div>
    <div class="left">左边固定宽度</div>
    <div class="right">右边固定宽度</div>
</body>
</html>

display:table实现

<table>标签用于展示行列数据,不适合用于布局。但是可以使用
display:table来实现布局的效果
实现原理:

  • 外层通过display:table设置为表格,设置table-layout:fixed表示列宽自身宽度决定,而不是自动计算
  • 内层的左中右通过display:table-cell设置为表格单元
  • 左右设置固定宽度,中间设置width:100% 填充剩下的宽度
<!--
 * @Author: 41
 * @Date: 2021-12-07 11:02:36
 * @LastEditors: 41
 * @LastEditTime: 2021-12-07 11:07:24
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .container {
            height: 200px;
            line-height: 200px;
            text-align: center;
            display: table;
            table-layout: fixed;
            width: 100%;
        }
        .left,
        .right,
        .main {
            display: table-cell;
        }
        .left,
        .right {
            width: 100px;
            background: green;
        }
        .main {
            background: black;
            color: white;
            width: 100%;
        }       
    </style>
</head>
<body>
    <div class="container">
        <div class="left">左边固定宽度</div>
        <div class="main">中间自适应</div>
        <div class="right">右边固定宽度</div>
    </div>
</body>
</html>

flex实现

实现过程:

  • 容器设置为display:flex;
  • 盒内元素两端对齐,将中间元素设置为100%宽度,或者设为flex:1,即可填充空白
  • 盒内元素的高度撑开容器的高度

优点:

  • 结构简单直观
  • 可以结果flex的其他功能实现更多效果,例如使用order属性调整显示顺序,让主题内容优先加载,但展示在中间
<!--
 * @Author: 41
 * @Date: 2021-12-07 11:24:58
 * @LastEditors: 41
 * @LastEditTime: 2021-12-07 11:38:11
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .wrap {
            display: flex;
            justify-content: space-between;
        }

        .left,
        .right,
        .middle {
            height: 100px;
        }

        .left {
            width: 200px;
            background: coral;
        }

        .right {
            width: 120px;
            background: lightblue;
        }

        .middle {
            background: #555;
            width: 100%;
            margin: 0 20px;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="left">左侧</div>
        <div class="middle">中间</div>
        <div class="right">右侧</div>
    </div>
</body>
</html>

grid网格布局

和flex布局类似

<!--
 * @Author: 41
 * @Date: 2021-12-07 11:40:48
 * @LastEditors: 41
 * @LastEditTime: 2021-12-07 11:42:01
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .wrap {
            display: grid;
            width: 100%;
            grid-template-columns: 100px auto 100px;
        }
        .left,
        .right,
        .middle {
            height: 100px;
        }

        .left {
            background: coral;
        }

        .right {
            background: lightblue;
        }

        .middle {
            margin: 0 20px;
            background: #555;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="left">左侧</div>
        <div class="middle">中间</div>
        <div class="right">右侧</div>
    </div>
</body>
</html>

js:说说你对Javascript中this对象的理解

函数的this关键字在JavaScript中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别

在绝大多数情况下,函数的调用方式决定了this的值(运行时绑定)

this关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象

改变this指针

apply(),call(),bind()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的是第一个参数。
这个在后面的博客会细说

箭头函数

在 ES6 的语法中还提供了箭头函语法,让我们在代码书写时就能确定 this 的指向(编译时绑定)

  • 绑定事件监听要小心
const button = document.getElementById('mngb');
button.addEventListener('click', ()=> {
    console.log(this === window) // true
    this.innerHTML = 'clicked button'
})

上述可以看到,我们其实是想要this为点击的button,但此时this指向了window

  • 原型上添加方法,this指针指向window
Cat.prototype.sayName = () => {
    console.log(this === window) //true
    return this.name
}
const cat = new Cat('mm');
cat.sayName()

我们应该避免上面的情况,同样的,箭头函数不能作为构造函数

优先级

这里不细说了
new绑定优先级 > 显示绑定优先级 > 隐式绑定优先级 > 默认绑定优先级

ES6:你是怎么理解ES6中的Decorator的?使用场景?

Decorator,即装饰器,从名字上很容易让我们联想到装饰着模式
简单来讲,装饰着模式就是一种不再改变原类和使用继承的情况下,动态地扩展对象功能地设计理论。
ES6中Decorator功能意识如此,其本质也不是什么高大上的结构,就是一个普通的函数,用于扩展类属性和类方法

  • 这里定义一个士兵,这时候它什么装备都没有
class soldier{ 
}
  • 定义一个得到AK装备的函数,即装饰器
function strong(target){
    target.AK = true
}
  • 使用该装饰器对士兵进行增强
@strong
class soldier{
}
  • 这时候士兵就有武器了
soldier.AK // true

上述代码虽然简单,但也能够清晰看到使用了Decorator两大优点:

  • 代码可读性变强了,装饰器命名相当于一个注释
  • 在不改变原有代码情况下,对原来功能进行扩展

用法

  • 类的装饰
    当对类本身进行装饰的时候,能够接受一个参数,即类本身
    将装饰器行为进行分解如下
@decorator
class A {}

// 等同于

class A {}
A = decorator(A) || A;

下面@testable就是一个装饰器,target就是传入的类,即MyTestableClass,实现了为类添加静态属性

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true

如果想要传递参数,可以在装饰器外层再封装一层函数

function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true

@testable(false)
class MyClass {}
MyClass.isTestable // false

  • 类属性的装饰
    当对类属性进行装饰的时候,能够接受三个参数:
  • 类的原型对象
  • 需要装饰的属性名
  • 装饰属性名的描述对象

  • 首先定义一个readonly装饰器
function readonly(target, name, descriptor){
  descriptor.writable = false; // 将可写属性设为false
  return descriptor;
}
  • 使用readonly装饰类的name方法
class Person {
  @readonly
  name() { return `${this.first} ${this.last}` }
}
  • 相当于以下调用
readonly(Person.prototype, 'name', descriptor);

如果一个方法有多个装饰器,就像洋葱一样,线从外到内进入,再由内到外执行

function dec(id){
    console.log('evaluated', id);
    return (target, property, descriptor) =>console.log('executed', id);
}

class Example {
    @dec(1)
    @dec(2)
    method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1

外层装饰器@dec(1)线进入,但是内层装饰器@dec(2)先执行

使用场景

  • 使用react-redux的时候
class MyReactComponent extends React.Component {}

export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {}
  • mixins写成装饰器
function mixins(...list) {
  return function (target) {
    Object.assign(target.prototype, ...list);
  };
}

// 使用
const Foo = {
  foo() { console.log('foo') }
};

@mixins(Foo)
class MyClass {}

let obj = new MyClass();
obj.foo() // "foo"

vue:为什么data属性是一个函数而不是一个对象?

  • 根实例对象data可以是对象也可以是函数(根实例是单例),不会产生数据污染情况
  • 组件实例对象data必须为函数,目的是为了防止多个组件实例对象之间共用一个data,产生数据污染。采用函数的形式,initData时会将其作为工厂函数都会返回全新data对象
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值