教务出题,全栈请求出战1234(marksheng)

70 篇文章 1 订阅
3 篇文章 0 订阅

第一周

1.1.1:Vue解决了什么问题?

虚拟domdom操作时非常耗性能的,不再使用原生的dom操作节点,极大的解放dom操作,但具体操作的还是dom,不过是换了一种方式。
视图、数据、结构分离使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作。
组件化把一个单页应用中的各种模块拆分到一个一个单独的组件中,便于开发,以及后期的维护

1.1.2:MVVM的理解?

MVVM就是Model-View-ViewModel的缩写,MVVM将视图和业务逻辑分开。
View:视图层,Model数据模型,而ViewModel是把两者建立通信的桥梁。
在MVVM框架下,View和Model之间没有直接的联系,而是通过ViewModel进行交互。View和ViewModel之间以及Model和ViewModel之间的交互都是双向的,因此view数据的变化会同步到Model中,而Model数据的变化也会立即反映到View上。可以说它们两者是实时更新的,互相影响。  ViewModel通过双向数据绑定把View层和Model层连接了起来,而View和Model之间的同步工作完全是自动的,因此开发者只需要关注业务逻辑,不需要手动操作DOM,也不需要关注数据状态的同步问题,这些都由MVVM统一管理。

 

1.1.3:如何实现一个自定义组件? 

自定义组件:

  创建子组件的文件,建立组件的模板,把架子搭起来,也就是在子组件中写好<template>视图层,<script>逻辑层<style>css样式层。然后定义好props里面的数据,实现子组件需要的逻辑代码后,也就封装好了,然后直接调用即可。调用的花import引入,同时在父组件<script>(逻辑层)中的components这个对象中写入组件名称,最后挂载到父组件的template中即可。

1.1.4:不同组件之间是如何通信的

请永远牢记vue是单向数据流

组件通信:

①props / $emit

父组件通过props的方式向子组件传递数据,而通过$emit子组件可以向父组件通信。

②$children / $parent

this.$children[0].msg = "hello world" //父组件修改子组件data中的数据

this.$parent.mag //子组件拿到父组件data中的数据

 

$children的值是数组,$parent的值是个对象

注意:$parent,$children它们的目的是作为访问数组的应急方法,更推荐用props和events实现父子组件通信。

③provide / inject

这是vue2.2.0新增的api,简单来说就是父组件中通过provide来提供变量,然后再子组件中通过inject来注入变量。

//父组件

export default{

    name:"A",

    provide:{

        for:"demo"

    },

    components:{

        comB

    }

}

 

//子组件

export default{

    name:"B",

    inject:["for"],

    data(){

        demo:this.for

    }

}复制代码

④ref / refs

ref:如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例,可通过实例直接调用组件的方法或访问数据。

//父组件

<template>

    <component-a ref="comA"></component-a>

</template>

<script>

    export default{

        mounted(){

            const comA = this.$refs.comA;

            console.log(comA.name)//Vue.js

            comA.sayHello() //hello

        }

    }

</script>

 //子组件

export default{

    data(){

        return {

            name:"Vue.js"

        }

    },

    methods:{

        sayHello(){

            console.log("hello")

        }

    }

⑤eventBus(Bus总线):

//首先在src中创建一个Bus文件夹 => index.js

import Vue from "vue";

export default new Vue({

    

})

 

//子组件1(发送数据的组件)

<button @click="add()">点击</button>

import Bus from "@/Bus"

add(){

    Bus.$emit("add",this.content);

}

 

//子组件2(接受数据的组件)

<p>{{tit}}</p>

import Bus from "@/Bus";

created(){

    Bus.$on("add",(data) => {

        this.tit = data;

    })

⑥Vuex;

⑦LocalStorage;

⑧$attrs / $listeners

     将数据挂在到子组件的标签上去后,在子组件中使用this.$attrs直接获取到所有挂载的数据,返回的是一个对象。 

1.1.5:nextTick 的理解?

使用nextTick的原因Vue是异步修改DOM的,并且不鼓励开发者直接接触DOM,但是有时候需要必须对数据更改后的DOM元素做相应的处理,但是获取到的DOM数据并不是更改后的数据,这时候就需要this.$nextTick();

原理:Vue通过异步队列控制DOM更新和nextTick回调函数先后执行的方式

使用:

//HTML

<button @click="change()">按钮</button><h1 ref="gss">{{msg}}</h1>

//JS

export default{

    name:"app",

    data(){

        return {

            msg:"123"

        }

    },

    methods:{

        change(){

            this.msg = "456";

            console.log(this.refs["gss"].innerHTML)//123

            this.$nextTick(function(){

                console.log(this.refs["gss"].innerHTML)//456

            })

        }

    }

    

}

 

1.1.6:Vue的生命周期(11个钩子函数)

⑴beforeCreate(创建前):在此生命周期函数执行的时候,data和methods中的数据都还没有初始化。

⑵created(创建后):在此生命周期函数中,data和methods都已经被初始化好了,如果要调用 methods中的方法,或者操作data中的数据,最早只能在created中操作。

⑶beforeMount(载入前):在此生命周期函数执行的时候,模板已经在内存中编译好了,但是尚未挂载到页面中去,此时页面还是旧的。

⑷mounted(载入后):此时页面和内存中都是最新的数据,这个钩子函数是最早可以操作dom节点的方法。

⑸beforeUpdate(更新前):此时页面中显示的数据还是旧的,但是data中的数据是最新的,且页面并未和最新的数据同步。

⑹Updated(更新后):此时页面显示数据和最新的data数据同步。

⑺beforeDestroy(销毁前):当执行该生命周期函数的时候,实例身上所有的data,所有的methods以及过滤器......等都处于可用状态,并没有真正执行销毁。

⑻destroyed(销毁后):此时组件以及被完全销毁,实例中的所有的数据、方法、属性、过滤器......等都已经不可用了。

//下面两个钩子函数一般配合<keep-alive></keep-alive>使用

⑼activated(组件激活时):和上面的beforeDestroy和destroyed用法差不多,但是如果我们需要一个实例,在销毁后再次出现的话,用beforeDestroy和destroyed的话,就太浪费性能了。实例被激活时使用,用于重复激活一个实例的时候
⑽deactivated(组件未激活时):实例没有被激活时。
⑾errorCaptured(错误调用):当捕获一个来自后代组件的错误时被调用

1.1.7: 虚拟DOM原理

虚拟DOM,其实就是用对象的方式取代真实的DOM操作,把真实的DOM操作放在内存当中,在内存中的对象里做模拟操作。当页面打开时浏览器会解析HTML元素,构建一颗DOM树,将状态全部保存起来,在内存当中模拟我们真实的DOM操作,操作完后又会生成一颗dom树,两颗DOM树进行比较,根据diff算法比较两颗DOM树不同的地方,只渲染一次不同的地方。

补充:

diff算法核心:

①如何用vnode生成一个dom的节点

patch方法patch(container, vnode)patch(vnode, newVnode) 

②vnode和newVnode的对比

③修改改变的dom节点

replacechildrencreateElement

1.1.8:双向绑定的原理?数据劫持?

mvvm 双向绑定,采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

 

几个要点:
1、实现一个数据监听器 Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器 Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个 Watcher,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4、mvvm 入口函数,整合以上三者

具体步骤:

  1. 需要 observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter
    这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化
  2. compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
  3. Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情是:
    • 在自身实例化时往属性订阅器(dep)里面添加自己
    • 自身必须有一个 update() 方法
    • 待属性变动 dep.notice() 通知时,能调用自身的 update() 方法,并触发 Compile 中绑定的回调,则功成身退。
  1. 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过Observer来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变更的双向绑定效果。

 

1.1.9:Proxy相比于defineProperty的优势

Vue3.0摒弃了Object.defineProperty,改为基于Proxy的观察者机制探索。

首先说一下Object.defineProperty的缺点

  • ①Object.defineProperty无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实施响应。
  • ②Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue2.X里,是通过递归 + 遍历data对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象才是更好的选择。

而要取代它的Proxy有以下两个优点:

  • 可以劫持整个对象,并返回一个新对象。
  • 有多种劫持操作(13种)

补充:

  • Proxy是ES6新增的一个属性,翻译过来的意思就是代理,用在这里表示由它来“代理”某些操作。Proxy让我们能够以简洁易懂的方式控制外部对象的访问,其功能非常类似于设计模式中的代理模式。
  • Proxy可以理解为,在目标对象之前设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
  • 使用Proxy的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。从而可以让对象只需要关注核心逻辑,达到关注点分离,降低对象复杂度等目的。

1.1.10:watch、computed和methods的区别

·  methods即是方法,封装的功能代码块,调用后执行。在重新渲染的时候每次都会被重新的调用;

·  computed 是自动监听依赖值的变化,从而动态返回内容,主要目的是简化模板内的复杂运算。所以区别来源于用法,只是需要动态值,那就用 computed ;需要知道值的改变后执行业务逻辑,才用 watch。

·   watch也可以影响数据的变化,当绑定的数据方法变化时触发响应的函数,需要在数据变化时执行异步或开销较大的操作时使用watch。

 

1.1.11:virtual-dom原理实现(虚拟dom)

virtual-dom(简称vdom)的概念大规模的推广还是得益于react的出现,virtual-dom也是react这个框架的非常重要的特性之一。相比于频繁的手动去操作dom而带来性能问题,vdom很好的将dom做了一层映射关系,进而将在我们本需要直接进行dom的一系列操作,映射到了操作vdom,而vdom上定义了关于真实dom进行的创建节点,删除节点,添加节点等一系列复杂的dom操作,并将这些操作放到vdom中进行,这样就通过操作vdom来提高直接操作的dom的效率和性能。

  在vue的整个应用生命周期当中,每次需要更新视图的时候便会使用vdom,vdom算法是基于snabbdom算法所做的修改。

实现:

     ①用js对象构造一个虚拟的dom树,插入到文档中;
     ②状态变更时,记录新树和旧树的差异;
     ③把上面的差异构建到真正的dom中。

1.1.12:vue-router路由模式

①hash(哈希默认)模式:使用 URL hash 值来作路由。默认模式。
②history(mode:history)模式: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。
③abstract模式(严格模式):支持所有 JavaScript 运行环境,如 Node.js 服务器端。
根据mode参数来决定采用哪一种方式。

vue-router的实现原理(核心):更新视图但不重新请求页面。

1.1.13: vue-router登陆权限的判断

vue-router的登陆权限判断主要是在全局钩子函数中进行的,我们在router.js文件中的定义路由里,将需要登陆权限的页面加上meta属性,值是对象的形式,然后在该对象中自定义一个属性,属性值就是一个Boolean值,这时候在main.js文件的全局钩子函数中进行判断,如果需要跳转的页面的自定义属性值为true,那么将进行判断其是否登录,如果没有登录,则告诉用户登录,如果有登录,那么进行页面跳转。

routes:[

    {

        path:"/home",

        name:"Home",

        components:Home

        meta:{requireAuth:true}

    }

router.beforeEach((to,from,next) => {

    if(to.meta.requireAuth){//判断该路由是否需要登录权限

        if(store.state.token){//通过vuex的state获取当前的token是否存在

            next()

        }else{

            next({

                path:"/one",

                query:{redirect:to.fullPath}//将跳转的路由path作为参数,登陆成功后跳转到该路由

            })

        }

    }else{

        next();

    }    

})

1.1.14:vue-router路由嵌套

routes:[

{

  path:"/home",

name:"Home",

       components:Home,

    children:[

{

path:"child", name:"Child",

   components:"Child"

}

]

} ]

 

1.1.15: Vuex的理解Vuex的五大核心

定义:Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式储存管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

使用场景:需要构建一个中大型单页应用,您很可能会考虑如何更好的在组件外部管理状态,Vuex将会成为自然而然的选择。

优点:当你在state中定义了一个数据之后,可以在所在项目中的任何一个组件里进行获取、进行修改、并且你的修改可以得到全局的响应变更。

①state:定义初始数据。
②mutations:更改Vuex的store中的状态的唯一方法是提交mutation
③getters:可以对 state 进行计算操作,它就是 store 的计算属性虽然在组件内也可以做计算属性,但是 getters 可以在多给件之间复用如果一个状态只在一个组件内使用,是可以不用 getters。
④actions:异步操作初始数据,其实就是调用mutations里面的方法。
⑤module:面对复杂的应用程序,当管理的状态比较多时;我们需要将vuex的store对象分割成模块(modules)。

 

1.1.16 : Vue.js的特点

  • 简洁:页面由HTML模板+Json数据+Vue实例组成
  • 数据驱动:自动计算属性和追踪依赖的模板表达式
  • 组件化:用可复用、解耦的组件来构造页面
  • 轻量:代码量小,不依赖其他库
  • 快速:精确有效批量DOM更新
  • 模板友好:可通过npm,bower等多种方式安装,很容易融入

1.1.17:Vuex的运行机制?

Vuex提供数据(state)来驱动视图(vue components),通过dispath派发actions,在其中可以做一些异步的操作,然后通过commit来提交mutations,最后mutations来更改state。

 

1.1.18:Vuex的映射?

state(数据)、getters(计算属性)需要映射在computed实例中,而mutations(同步操作放),actions(异步操作方法)等需要放在methods实例中

computed:{

    ...mapState([

        "list",

    ])

}

methods:{

    ...mapMutations([

        "changes",

    ])

}

 

 

1.1.19:描述下vue从初始化页面-->修改数据-->刷新页面UI过程?

当Vue进入初始化阶段时,一方面Vue会遍历data中的属性,并用Object.defineProperty将它转化成getter/setterd的形式,实现数据劫持;另一方面,Vue的指令编译器Compiler对元素节点的各个指令进行解析,初始化视图,并订阅Watcher来更新视图,此时Watcher会将自己添加到消息订阅器Dep中,此时初始化完毕。
当数据发生变化时,触发Observer中setter方法,立即调用Dep.notify( ),Dep这个数组开始遍历所有的订阅者,并调用其update方法,Vue内部再通过diff算法,patch相应的更新完成对订阅者视图的改变。

1.1.20:Vue的响应式原理

当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

 

 

 


第二周

1.2.1:插槽的理解

插槽用于决定将所携带的内容,插入到子组件指定的某个位置,但内容必须在父组件中子组件的标签内定义,在子组件中用<slot></slot>标签接收。slot 就是 子组件向父组件暴露的接口,父组件可以通过v-slot 来管理接口

 

1.2.2:vue-router有哪几种导航钩子

① 全局导航钩子:一般用来判断权限,以及页面丢失时需要执行的操作;

     beforeEach()每次路由进入之前执行的函数。

     afterEach()每次路由进入之后执行的函数。

     beforeResolve()2.5新增

② 单个路由(实例钩子):某个指定路由跳转时需要执行的逻辑。

     beforeEnter()

     beforeLeave()

③ 组件路由钩子:

    beforeRouteEnter()

    beforeRouteLeave()

    beforeRouteUpdate()

 

1.2.3:vue组件中的data为什么是一个函数

如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。Object是引用数据类型,里面保存的是内存地址,单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。

所以说vue组件的data必须是函数。

1.2.4:路由懒加载

路由懒加载的应用场景:当项目很大的时候,为了提升用户体现,则必须使用懒加载。否则,首页会一次导入所有页面与组件。需要加载的内容过多,延时过长,不利于用户体验。但项目很小,则不推荐使用,项目小,分开后的懒加载会发多次请求,带来更多的性能缺陷;

路由懒加载的原理:vue 异步组件技术:异步加载,vue-router 配置路由 , 使用 vue 的异步组件技术 , 实现按需加载。

 

常用的懒加载方式有两种:即使用vue异步组件 和 ES中的import

1、vue异步组件实现路由懒加载

 

component:resolve=>(['需要加载的路由的地址',resolve])

 

2、es提出的import(推荐使用这种方式)

 

const HelloWorld = ()=>import('需要加载的模块地址')

1.2.5:Vue.js介绍

Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API;Vue.js是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。数据驱动+组件化的前端开发。通过尽可能简单的 API实现响应的数据绑定和组合的视图组件。核心是一个响应的数据绑定系统。

1.2.6:scoped原理及穿透方法

scoped的作用

在vue文件中的style标签上,有一个特殊的属性:scoped。当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,也就是说,该样式只能适用于当前组件元素。通过该属性,可以使得组件之间的样式不互相污染。如果一个项目中的所有style标签全部加上了scoped,相当于实现了样式的模块化。

 

scoped实现原理

vue中的scoped属性的效果主要通过PostCSS转译实现PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,然后,给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom,这种做法使得样式只作用于含有该属性的dom——组件内部dom

 

为什么需要穿透scoped?

 

scoped看起来很美,但是,在很多项目中,会出现这么一种情况,即:引用了第三方组件,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成组件之间的样式污染。此时只能通过特殊的方式,穿透scoped

 

方法一:

 

通过 >>> 可以使得在使用scoped属性的情况下,穿透scoped,修改其他组件的值。

 

方法二:

定义一个含有scoped属性的style标签之外,再定义一个不含有scoped属性的style标签,即在一个vue组件中定义一个全局的style标签,一个含有作用域的style标签:

 

此时,你只需要将修改第三方样式的css写在第一个style中即可。

 

个人推荐方法:

以上两种方法,穿透方法实际上违反了scoped属性的意义,曲线救国的方法又使得代码太过于难看。

 

个人推荐第三种方法,即:由于scoped看起来很美好,但是含有很多的坑,所以,不推荐不使用scoped属性,而***通过在外层dom上添加唯一的class来区分不同组件***。这种方法既实现了类似于scoped的效果,又方便修改各种第三方组件的样式,代码看起来也相对舒适。

1.2.7:请说出vue.cli项目中src目录每个文件夹和文件的用法

assets文件夹是放静态资源;
components是放组件;
router是定义路由相关的配置;
view视图;
app.vue是一个应用主组件;
main.js是入口文件

1.2.8:Vue中key值的作用

key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法,也就是所谓的就地复用策略。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。key的作用是辅助判断新旧vdom节点在逻辑上是不是同一个对象。
所以,渲染列表时,key值需要一个唯一确定的id来赋值。key 的作用主要是为了高效的更新虚拟DOM

1.2.9:Vue怎么重置data

使用Object.assign(),vm.$data可以获取当前状态下的data,vm.$options.data可以获取到组件初始化状态下的data。

 

Object.assign(this.$data, this.$options.data())

1.2.10:组件中写name选项有什么作用

    ①项目使用keep-alive时,可搭配组件的name进行缓存过滤。
    ②DOM做递归组件时需要调用自身name
    ③vue-devtools调试工具里显示的组件名称是由vue中组件name决定的

1.2.11:route和router

route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。

router是“路由实例对象”,包括了路由的跳转方法(pushgo),钩子函数等。

1.2.12:Vue和React的区别

·监听数据变化的实现原理不同:Vue 通过 getter/setter 以及一些函数的劫持,能精确快速的计算出 vdom 的差异。这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。React 默认是通过比较引用的方式进行的,如果不优化,每当应用的状态被改变时,全部子组件都会重新渲染,可能导致大量不必要的 VDOM 的重新渲染。

·数据流的不同:Vue 中默认支持双向绑定,组件与 DOM 之间可以通过 v-model 双向绑定。但是,父子组件之间,props 在 2.x 版本是单向数据流。React 一直提倡的是单向数据流。

·模板渲染方式的不同:React 是通过 JSX 渲染模板,而 Vue 是通过一种拓展的 HTML 语法进行渲染

1.2.13:首屏加载优化

①把不常改变的库放到index.html中,通过cdn引入

 

然后找到 build/webpack.base.conf.js 文件,在 module.exports = { } 中添加以下代码:

externals: {

  'vue': 'Vue',

  'vue-router': 'VueRouter',

  'element-ui': 'ELEMENT',

},复制代码

②vue路由懒加载(利用Webpack的代码切割)

③不生成map文件,找到config/index.js文件,修改为productionSourcceMap:false

④vue组件尽量不要全局引入

⑤使用更轻量级的工具库

⑥开启gzip压缩:这个优化是两方面的,前端将文件打包成.gz文件,然后通过nginx的配置,让浏览器直接解析.gz文件。

⑦首页单独做服务端渲染:如果首页真的有瓶颈,可以考虑用 node 单独做服务端渲染,而下面的子页面仍用 spa 单页的方式交互。这里不推荐直接用 nuxt.js 服务端渲染方案,因为这样一来增加了学习成本,二来服务端的维护成本也会上升,有时在本机测试没问题,在服务端跑就有问题,为了省心,还是最大限度的使用静态页面较好。

1.2.14:Vue3.0的了解

1. VUE 3.0 六大特点

性能比Vue2.x 快1.2~2倍

支持按需导入,体积比Vue2.x更小

支持组合API (类似React Hooks)

更好的支持 TS

暴露出自定义渲染API

更先进的组件

  1. VUE 3.0 与 VUE 2.0的区别

1. diff方法优化

vue2中的虚拟DOM是进项全量对比

vue3新增了静态标记(PatchFlag)

在与上次虚拟节点进行对比的时候,只对比带有Patch Flag的节点

并且可以通过flag的信息得知当前节点要对比的具体内容

2. 静态提升

vue2中无论元素是否参与更新,每次都会重新创造

vue3中对于不参与更新的元素,只会被创建一次,之后会在每次渲染时候被不停的复用

3. 事件侦听器缓存

默认情况下,事件会被视为动态绑定(可以把事件看做是一个动态属性),所以每次都会追踪它的变化。但是因为同一个事件名都是同一个函数,所以就不需要对其进行动态绑定,也就不会追踪变化,直接缓存起来复用即可,因为不用追踪。所以也就节省了性能

  1. VUE3.0的监听机制有了很大的改善,弥补了vue2.0的不足:

vue3.0 使用proxy代替了vue2.0版本中的defineProperty,首先利用compositionAPI中的 reactive() 函数返回一个proxy对象,使得数据可监测。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写

 

1.2.15:vue-cli替我们做了哪些工作

vue-cli是基于 Vue.js 进行快速开发的完整系统,也可以理解成是很多 npm 包的集合。

.vue 文件 --> .js 文件

ES6 语法 --> ES5 语法

Sass,Less,Stylus --> CSS

对 jpg,png,font 等静态资源的处理

热更新

定义环境变量,区分 dev 和 production 模式

如果开发者需要补充或修改默认设置,需要在 package.json 同级下新建一个 vue.config.js 文件中进行修改

 

1.2.16:vue的指令

⑴v-bind:给元素绑定属性

⑵v-on:给元素绑定事件

⑶v-html:给元素绑定数据,且该指令可以解析html标签

⑷v-text:给元素绑定数据,不解析标签

⑸v-model:数据双向绑定

⑹v-for:遍历数组

⑺v-if:条件渲染指令,动态在DOM内添加或删除DOM元素

⑻v-else:条件渲染指令,必须跟v-if成对使用

⑼v-else-if:判断多层条件,必须跟v-if成对使用

⑽v-cloak:解决插值闪烁问题

⑾v-once:只渲染元素或组件一次

⑿v-pre:跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度

⒀v-show:条件渲染指令,将不符合条件的数据隐藏(display:none)

1.2.17:v-for 与 v-if 的优先级

v-for比v-if优先,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候。

1.2.18:axios的拦截

要想统一处理所有http请求和响应,就得用上 axios 的拦截器

//响应拦截

axios.interceptors.response.use(function(response){

    //对响应数据做点什么

    return response.data

},function(error){

    //对错误响应做点什么

    return Promise.reject(error)

})

//请求拦截

axios.interceptors.request.use(function(config){

    //在发送请求之前做些什么

    return config

},function(error){

    //对请求错误做些什么

    return Promise.reject(error)

})

1.2.19:vue怎么兼容IE

使用babel-polyfill插件

1.2.20:$set是干嘛用的

<template>

<h1>{{arr}}</h1>

<button @click="change()">点击</button>

</template>

<script>

export default {

data(){ return { arr:[1,2,3] } },     `  

methods:{

     change(){

this.arr[1]=0; console.log(this.arr); //[1,0,3]

}

}

}

</script>

上面就是一个典型的例子,当我们点击按钮想要根据数组arr的下标改变其元素的时候,你会发现data中的数据改变了,但是页面中的数据并没有改变。这时候就需要$set出场了。

change(){

    this.$set(this.list,1,0);

}

改变/添加 对象属性的时候:this.$set(data实例,"属性名(添加的属性名)","属性值(添加的属性值)")

改变/添加 数组属性的时候:this.$set(data实例,数组下标,"改变后的元素(添加的元素)")

原因:

vue在创建实例的时候把data深度遍历所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。让 Vue 追踪依赖,在属性被访问和修改时通知变化。所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

当你在对象上新加了一个属性newProperty,当前新加的这个属性并没有加入vue检测数据更新的机制(因为是在初始化之后添加的),vue.$set是能让vue知道你添加了属性, 它会给你做处理。

 

 


第三周

1.3.1:HTML语义化的理解

html语义化的含义:根据内容的结构化,选择合适的标签便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析。(基本上都是围绕着几个主要的标签,像标签H1~H6,li、强调(strong、em)等等)。

语义化的原因:

①为了在没有CSS情况下,页面也能呈现出很好的内容结构、代码结构。(为了裸奔时候好看)。
用户体验:例如title、alt用于解释名词或者解释图片信息、label标签dd的活用。
有利于SEO:和搜索引擎建立良好的沟通,有助于爬虫抓取更多的有效信息(爬虫依赖于标签来确定上下文和各个关键字的权重)。
④方便其它设备解析(如屏幕阅读器,盲人阅读器,移动设备)以意义的方式来渲染网页。
⑤便于团队开发和维护,语义化更具可读性,遵循W3C标准的团队都遵循这个标准,可以减少差异化。

1.3.2:  HTML5新增了哪些语义化标签

               

<article> 定义文章

 

<aside> 定义文章的侧边栏

 

<figure> 一组媒体对象以及文字

 

<figcaption> 定义 figure 的标题

 

<footer>定义页脚

 

<header>定义页眉

 

<hgroup>定义对网页标题的组合

 

<nav>定义导航

 

<section> 定义文档中的区段

 

<time>定义日期和时间

 

<dialog>定义一个对话框

<section><section> 页面上的版块

用于划分页面上的不同区域,或者划分文章里不同的节

<article></ article > 

 

用来在页面中表示一套结构完整且独立的内容部分,可以用来呈现论坛的一个帖子,杂志或报纸中的一篇文章,一篇博客,用户提交的评论内容等。

 

<figure> 标签规定独立的流内容(图像、图表、照片、代码等等)。

<figcaption> figure的子元素 用于对figure的内容 进行说明

<datalist></datalist>选项列表。与 input 元素配合使用,来定义 input 可能的值。

<mark></mark> 需要标记的词或句子
<details></details>用于描述文档或文档某个部分的细节
< summary></summary> details 元素的标题
该元素用于摘录引用等 应该与页面的主要内容区分开的其他内容

1.3.3:H5的新特性

语义化标签(上面题)。

本地存储(localStorage)。

localStorage.setItem("name",arr);//保存数据localStorage.getItem("name")//读取数据,也可以根据key值读取localStorage.removeItem(key)//删除单个数据localStorage.clear()//数据清空

③播放音频文件的标签。

<audio></audio>音频

<video></video>视频

Canvas使用Javascript来绘制图像,canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成

<canvas id="myCanvas" width="200" height="100" style="1px solid #000000"></canvas>

SVG绘图:一种使用XML描述2D图像的语言。

progress元素 :标签定义运行中的进度(进程)

<progressvalue="0" max="100"></progress> 

meter元素 :标签定义度量衡。仅用于已知最大和最小值的度量。

<metervalue="70" max="100" min="0"></meter>

1.3.4: input和textarea的区别

<input>是单行文本框,不会换行。通过size属性指定显示字符长度,注意:当使用css限定了宽高,那么size属性就不再起作用了。value属性指定初始值,Maxlength属性指定文本框可以输入的最长长度。可以通过width和height设置宽高,但是也不会增加行数。

<input type="text" value="你好" Maxlength="10">

<textarea>是多行文本输入框,文本区中可容纳无限数量的文本,无value属性,其中的文本默认字体是等宽字体(通常是Courier),可通过cols和rows属性来规定textarea的尺寸,不过更好的办法是使用CSS的height和width属性。

<textarea cols="20" rows="30"></textarea>

 

1.3.5: 用一个div模拟textarea的实现

contenteditable属性,值为Boolean值,true绑定元素可编辑,false(默认)元素不可编辑。

<div id="textarea" contenteditable="true">

 

<style>

#textarea{

    width:300px;

    border:1px solid #ccc;

    min-height:150px;

    max-height:300px;

    overflow:auto;

    font-size:14px;

    outline:none;

}

</style>

1.3.6: 移动设备忽略将页面中的数字识别为电话号码的方法?

标准的电话号码格式是这样子的:

<a href="tel:1-408-555-555">1-408-555-555</a>

但是有时候不是电话号码的数字也会被浏览器自动解析为电话号码,并把数字的颜色和样式都改了,如果忽略页面中的数字识别为电话号码,只要把这个默认行为关闭即可,只要一行代码

<meta name="format-detection" content="telephone=no">

这个关闭不会影响真正电话号码的识别。

补充:format-detection属性和含义

format-detection翻译成中文的意思是“格式检测”,顾名思义,它是用来检测html里的一些格式的,那关于meta的format-detection属性主要是有以下几个设置:

<meta name="format-detection" content="telephone=no">

//禁止了把数字转化为拨号链接

<meta name="format-detection" content="email=no">

//告诉设备不识别邮箱,点击之后不自动发送

<meta name="format-detection" content="adress=no">

//禁止跳转至地图!

<metaname="format-detection"content="telephone=no,email=no,adress=no">

//以上三者组合

 

1.3.7: 你做的页面在哪些流览器测试过?这些浏览器的内核分别是什么?

Trident内核:IE系列

Gecko内核:Firefox

Webkit内核:Safari

Blink内核:是基于Webkit内核的子项目,使用的浏览器有:

Chrome/opera等除IE、Firefox、Safari之外的几乎所有浏览器

几乎所有国产双内核浏览器(Trident/Blink)如360、猎豹、qq、百度等

1.3.8 : px和em和rem的区别

1、px实际上就是像素,与物理像素有一定的区别,用px设置字体大小,比较精确,但是有缺点,当浏览器页面缩放时,px并不能跟随变大。当前网页的布局就会被打破。

2、em是根据基准来缩放字体的大小。em是相对单位,一般都是以<body>的字体大小作基准的。em是相对于父元素的属性来计算的,这样就会存在一个问题,就是每一层父元素都必须有它的数值。

3、而rem不同,rem是相对于根元素html,而此时我们只需要以rem为基准就可以了

1.3.9: 你能描述一下渐进增强和优雅降级之间的不同吗?

渐进增强 progressive enhancement:针对版本浏览器进行构建页面,保证最基本的功能,然后再针对级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

 

优雅降级 graceful degradation:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容

 

区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。

 

“优雅降级”观点:

“优雅降级”观点认为应该针对那些最高级、最完善的浏览器来设计网站。而将那些被认为“过时”或有功能缺失的浏览器下的测试工作安排在开发周期的最后阶段,并把测试对象限定为主流浏览器(如 IE、Mozilla 等)的前一个版本。

在这种设计范例下,旧版的浏览器被认为仅能提供“简陋却无妨 (poor, but passable)” 的浏览体验。你可以做一些小的调整来适应某个特定的浏览器。但由于它们并非我们所关注的焦点,因此除了修复较大的错误之外,其它的差异将被直接忽略。

 

“渐进增强”观点:

“渐进增强”观点则认为应关注于内容本身,内容是我们建立网站的诱因。有的网站展示它,有的则收集它,有的寻求,有的操作,还有的网站甚至会包含以上的种种,但相同点是它们全都涉及到内容。这使得“渐进增强”成为一种更为合理的设计范例。这也是它立即被 Yahoo! 所采纳并用以构建其“分级式浏览器支持 (Graded Browser Support)”策略的原因所在。

 

1.3.10:请描述一下cookies,sessionStorage和localStorage的区别?

sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。

localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

 

webStorage和cookie的区别

 

WebStorage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。

除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生。

1.3.11:简述一下src与href的区别。

src用于替换当前元素,href用于在当前文档和引用资源之间确立联系。

 

src是source的缩写,指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素。

<script src =”js.js”></script>

当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。

 

href是Hypertext Reference的缩写,指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,如果我们在文档中添加

<link href=”common.css” rel=”stylesheet”/>

那么浏览器会识别该文档为css文件,就会并行下载资源并且不会停止对当前文档的处理。这也是为什么建议使用link方式来加载css,而不是使用@import方式。

1.3.12:知道的网页制作会用到的图片格式有哪些?

png-8,png-24,jpeg,gif,svg等

 

但是上面的那些都不是面试官想要的最后答案。面试官希望听到是Webp。(是否有关注新技术,新鲜事物)

科普一下WebpWebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。Facebook Ebay等知名网站已经开始测试并使用WebP格式。

在质量相同的情况下,WebP格式图像的体积要比JPEG格式图像小40%

1.3.13:一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。

图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。

如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。

如果图片为css图片,可以使用CSSsprite,SVGsprite,Iconfont、Base64等技术。

如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。

如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。

 

1.3.14:谈谈以前端角度出发做好SEO需要考虑什么?

搜索引擎主要以:

 

外链数量和质量

网页内容和结构

来决定某关键字下的网页搜索排名。

前端应该注意网页结构和内容方面的情况:

Meta标签优化

主要包括主题(Title),网站描述(Description)。还有一些其它的隐藏文字比如Author(作者),Category(目录),Language(编码语种)等。

符合W3C规范的语义性标签的使用。

如何选取关键词并在网页中放置关键词

搜索就得用关键词。关键词分析和选择是SEO最重要的工作之一。首先要给网站确定主关键词(一般在5个上下),然后针对这些关键词进行优化,包括关键词密度(Density),相关度(Relavancy),突出性(Prominency)等等。

 

那么我们为什么需要做SEO呢,就是为了提高网站的权重,增强搜索引擎友好度,以达到提高排名,增加流量,改善用户体验,促进销售的作用。

1.3.15:行内元素和块级元素的具体区别是什么?行内元素的padding和margin可设置吗?

块级元素(block)特性:

总是独占一行,表现为另起一行开始,而且其后的元素也必须另起一行显示;

宽度(width)、高度(height)、内边距(padding)、边框(border)和外边距(margin)都可控制;

内联元素(inline)特性:

和相邻的内联元素在同一行;

宽度(width)、高度(height)、内边距的top/bottom(padding-top/padding-bottom)和外边距的top/bottom(margin-top/margin-bottom)还有border top/bottom都不可改变(也就是padding和margin的left和right是可以设置的),就是里面文字或图片的大小。

浏览器还有默认的天生inline-block元素(拥有内在尺寸,可设置高宽,但不会自动换行)

答案:<input> 、<img> 、<button> 、<texterea> 、<label>。

1.3.16:什么是外边距重叠?重叠的结果是什么?

外边距重叠就是margin-collapse。

在CSS当中,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为折叠,并且因而所结合成的外边距称为折叠外边距。

折叠结果遵循下列计算规则:

两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。

两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。

两个外边距一正一负时,折叠结果是两者的相加的和。

1.3.17:css中可以让文字在垂直和水平方向上重叠的两个属性是什么?

垂直方向:line-height

水平方向:letter-spacing

那么问题来了,关于letter-spacing的妙用知道有哪些么?

答案:可以用于消除inline-block元素间的换行符空格间隙问题。

1.3.18:如何垂直居中一个浮动元素?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

// 方法一:已知元素的高宽

#div1{

    background-color:#6699FF;

    width:200px;

    height:200px;

    position: absolute;        /*父元素需要相对定位*/

    top: 50%;

    left: 50%;

    margin-top:-100px ;   /*二分之一的height,width*/

    margin-left: -100px;

    }

 

//方法二:未知元素的高宽

 

  #div1{

    width: 200px;

    height: 200px;

    background-color: #6699FF;

 

    margin:auto;

    position: absolute;        /*父元素需要相对定位*/

    left: 0;

    top: 0;

    right: 0;

    bottom: 0;

    }

/*如何垂直居中一个<img>?(用更简便的方法。)*/ /*<img>的容器设置如下*/

 

 

 

 

 

 

 

#container{

   display:table-cell;

   text-align:center;

   vertical-align:middle;

}

1.3.19:Doctype作用? 严格模式与混杂模式-如何触发这两种模式,区分它们有何意义?

(1)、<!DOCTYPE> 声明位于文档中的最前面,处于 <html> 标签之前。告知浏览器的解析器,用什么文档类型 规范解析这个文档。

(2)、严格模式的排版和 JS 运作模式是,以该浏览器支持的最高标准运行

(3)、在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。

(4)、DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现

1.3.20:行内元素有哪些?块级元素有哪些? 空(void)元素有那些?

(1)CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,比如div默认display属性值为“block”,成为“块级”元素;span默认display属性值为“inline”,是“行内”元素。  

(2)行内元素有:a b span img input select strong(强调的语气) 块级元素有:div ul ol li dl dt dd h1 h2 h3 h4…p

(3)知名的空元素

<br><hr><img><input><link><meta>鲜为人知的是: <area><base><col><command>

<embed><keygen><param><source><track><wbr>

 


第四周

1、盒模型

标准盒模型:总宽度:content + border + padding + margin

怪异盒模型:宽度 : content + border + padding 

2、弹性盒模型

详细信息请参考:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

flex-direction:

row   //(默认)主轴为水平方向,起点在左端。
row-reverse   //主轴为水平方向,起点在右端
column   //使用后会使主轴变为y轴
column-reverse   //主轴为垂直方向,起点在下沿。

flex-wrap:

nowrap //(默认)不换行
wrap   //换行,第一行在上方
wrap-reverse   //换行,第一行在下方

flex-flow:该属性是flex-direction属性和flex-wrap属性的简写形式。
flex-flow:值1(主轴方向) 值2(是否换行)
row nowrap   //(默认)

justify-content:

flex-start   //(默认)左对齐
flex-end   //右对齐
center   //居中(子元素紧凑居中)
space-between;   //两端对齐,项目之间的间隔都相等
space-around;   //每个项目两侧的间隔相等

align-items:

flex-start   //与交叉轴的起点对其
flex-end   //与交叉轴的终点即末尾对其
center   //与交叉轴的中点对其
baseline   //项的第⼀⾏⽂字的基线对齐
stretch   //如果项未设置度或设为auto,将占满整个容器的

align-content属性,紧跟于flex-wrap属性后,该属性用于修饰flex-wrap属性
flex-start   //与交叉轴的起点对齐
flex-end   //与交叉轴的终点对其
center   //与交叉轴的中点对齐
space-between   //与交叉轴两端对齐,轴线之间的间隔平均分布
space-around   //每根轴线两侧的间隔都相等

align-self:center
//允许单个元素与其他元素有不一样的对齐方式
//在弹性子元素上使用。覆盖容器的 align-items 属性

align-self:flex-start   //默认
align-self:flex-end   //终点

order属性: (自定义子元素的显示顺序)
//用整数值来定义排列顺序,数值小的排在前面。可以为负值。
//注: 默认值为0。父元素必须设置为弹性盒模型

flex-grow属性:(定义弹性盒子元素的扩展比率)
//表示的是当容器有多余的空间时,这些空间在不同条目之间的分配比例
//比如,一个容器中有 3 个条目,其"flex-grow"属性的值分别为 1,2 和 3
//那么当容器中有空白空间时,这 3 个条目所获得的额外空白空间分别占
//全部空间的 1/6、1/3 和 1/2

flex-shrink属性:(定义弹性盒子元素的收缩比率)
//该属性的值也是无单位的,表示的是当容器的空间不足各个条目的尺寸缩小的比例。
//例如,在容器中有 3 个条目,其"flex-shrink"属性的值分别为 1,2 和 3。
//每个条目的主轴尺寸均为 200px。当容器的主轴尺寸不足 600px 时,
//比如变成了 540px 之后则需要缩小的尺寸 60px 由 3 个条目按照比例来分配。
//3 个条目分别要缩小 10px、20px 和 30px,
//主轴尺寸分别变为 190px、180px 和 170px

3、CSS单位

px:绝对单位。页面按精确像素展示。

em:相对单位,基准点为父节点字体的大小,如果自定义了font-size按自身的来算,整个页面内1em不是一个固定的值。14

rem:相对单位,相对于根节点html的font-size的大小来计算。

vw:视窗宽度1vw等于视窗宽度的1%。

vh:视窗高度1vh等于视窗高度的1%。

vmin:以宽和高之间最短的一端为基准,如果宽>高,那么1vmin相当于宽的1%;

vmax:以宽和高之间最长的一端为基准,如果宽>高,那么1vmax相当于宽的1%;

%:百分比

pt:point,大约1/72寸,一寸=3.3333···厘米。

pc:pica,大约6pt,1/6寸

ex取当前作用效果的字体的x的高度,在无法确定x高度的情况下以0.5em计算,IE11以下不支持。

ch以节点所使用字体中的“0”字符为基准,找不到时为0.5em。IE10以上支持。

4、CSS选择器

!important >内联样式> id选择器> class选择器>属性选择器>伪类选择器(: hover)>标签选择器>伪元素(: before)>通配符选择器

可继承的属性:

font-size、font-family、color

不可继承的属性:

border、padding、margin、width、height

权重值:

!important权重值:10000,

内联样式:1000,

id选择器:100

class、伪类、属性、伪元素选择器:10

标签选择器:1

后代选择器的权重为包含的选择符权重值之和。

CSS3新增的伪类:

p:first-of-type:选择属于其父元素的首个元素;

p:last-of-type:选择属于其父元素的最后元素;

p:only-of-type:选择属于其父元素的唯一元素;

p:only-child:选择属于其父元素的唯一子元素;

p:nth-child(1):选择属于其父元素的第一个子元素;

:enabled:disabled:表单控件d的禁用状态;

:checked:单选框h或复选框被选中;

5、BFC

BFC是块级格式化上下文。BFC它是一个独立的渲染区域,只有Block-level box(块元素)参与,它规定了内部的Block-level box如何布局,并且与这个区域外部毫不相关

可以理解成:创建了 BFC的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素(里面怎么布局都不会影响外部),BFC仍属于文档中的普通流

特性:

内部的块级元素会在垂直方向上一个接一个的放置;

位于同一BFC下的相邻块级子元素在垂直方向上会发生margin重叠;

位于不同BFC下的相邻元素之间不会发生margin重叠;

 BFC可以包含浮动元素;

 BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;

创建:

<html>根元素;

 float的值不为none

 overflow的值为auto、scroll或hidden

 display的值为:

table-cell:它会作为一个表格单元格显示(类似td和th)。

table-caption:此元素会作为一个表格标题显示。

inline-block:行内块元素。

 position的值为fixed或absolute

用途:

闭合浮动;

阻止margin重叠

自适应流体布局

6、清除浮动的方法

给设置了浮动的元素的父级加高

给设置了浮动的元素的父级设置overflow:hidden。如果需要兼容IE,在添加一个zoom:1

给需要清除浮动的元素设置clear:both

在最后一个子元素的后面加一个空的div,给它样式属性 clear:both(不推荐)

伪类清除:.clearfix:after{content:"";clear:both;display:block;}

.clearfix{zoom:1}

· 

7、层叠上下文

层叠上下文(stacking context),是HTML中一个三维的概念。在CSS2.1规范中,每个盒模型的位置是三维的,分别是平面画布上的X轴Y轴以及表示层叠的Z轴。一般情况下,元素在页面上沿X轴Y轴平铺,我们察觉不到它们在Z轴上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖。

通元素设置position属性为static值并设置z-index属性为具体数值,产生层叠上下文。

 

8、常见页面布局

静态布局:最传统、原始的Web布局设计。网页最外层容器(outer)有固定的大小,所有的内容以该容器为标准,超出宽高的部分用滚动条(overflow:scroll)来实现滚动查阅。

优点:采用的是css2之前的写法,不存在浏览器兼容性。布局简单。

缺点:但是移动端不可以使用pc端的页面,两个页面的布局不一致,移动端需要自己另外设计一个布局并使用不同域名呈现。

流式布局:流式布局也叫百分比布局。随着屏幕的改变,页面的布局没有发生大的变化,可以进行适配调整,这个正好与自适应布局相补。

优点:元素的宽高用百分比做单位,元素宽高按屏幕分辨率调整,布局不发生变化。

缺点:屏幕尺度跨度过大的情况下,页面不能正常显示。

弹性布局:弹性布局是CSS3引入的强大的布局方式,弹性盒模型:display:flex;

优点:简单、方便、快速

缺点:CSS3新特性,浏览器兼容性非常头疼。而且手机浏览器对flex的支持也不是很理想。

响应式布局:采用自适应布局和流式布局的综合方式,为不同屏幕分辨率范围创建流式布局。利用媒体查询可以检测到屏幕的尺寸(主要检测宽度),并设置不同的CSS样式,就可以实现响应式的布局。

9、CSS预处理,后处理

CSS预处理器:用一种编程语言,为CSS增加了一些编程的特性,最终编译出css文件。比如sass、less、stylus。

优点:语言级逻辑处理,动态特性,改善项目结构

缺点:采用特殊语法,框架耦合度高,复杂度高

实现原理:

取到 DSL 源代码的分析树

优点:使用 CSS 语法,容易进行模块化,贴近 CSS 的未来标准

缺点:逻辑处理能力有限

实现原理:

将源代码做为 CSS 解析,获得分析树

新增一:rgba(简单不做解释);

新增二:弹性布局flex(上面第二题);

新增三:媒体查询;

新增四:渐变色;

新增五:动画animation,使用@keyframes定义,使用的元素animation:名字时间; 

 

10、CSS3的新特性

新增一:rgba;

新增二:弹性布局flex;

新增三:媒体查询;

新增四:渐变色;

新增五:动画animation,使用@keyframes定义,使用的元素animation:名字 时间;

@keyframes changeWidth{

    0%{width:100px}

    100%{width:800px}

}

div{

    width:100px;

    height:100px;

    background:red;

    animation:changeWidth 10s forwards;

}复制代码

animation的6个值:

11、display有哪些值

1)、none:元素不会显示,而且改元素现实的空间也不会保留。但有另外一个 visibility: hidden,是保留元素的空间的。

2)、inline: display的默认属性。将元素显示为内联元素,元素前后没有换行符。我们知道内联元素是无法设置宽高的,所以一旦将元素的display 属性设为 inline,设置属性height和width是没有用的。此时影响它的高度一般是内部元素的高度(font-size)和padding。

3)、block:将元素将显示为块级元素,元素前后会带有换行符。设置为block后,元素可以设置width和height了。元素独占一行。

4)、inline-block:行内块元素。这个属性值融合了inline 和 block 的特性,即是它既是内联元素,又可以设置width和height。

5)、inherit:规定应该从父元素继承 display 属性的值。

12、相邻的两个inline-block节点为什么会出现间隔,该如何解决?

元素被当成行内元素排版的时候,原来HTML代码中的回车换行被转成一个空白符,在字体不为0的情况下,空白符占据一定宽度,所以inline-block的元素之间就出现了空隙。这些元素之间的间距会随着字体的大小而变化,当行内元素font-size:16px时,间距为8px。(不懂没关系,看下面解决方法就明白了)。

方法一:父级font-size:0;子级设置字体大小;

方法二:改变书写方式

方法三:margin负值

方法四:设置父元素display:table;word-spacing:0(两个记得都要加上);

13meta viewport移动端适配

禁止用户缩放

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

禁止自动识别电话号码,邮箱,地址

<meta name="format-detection" content="telephone=no,email=no,adress=no">

 

14CSS实现宽度自适应100%,宽高16:9的比例的矩形 

16、画三角形

div{
  width:0;
  height:0;
  border-top:50px solid transparent;
  border-left:50px solid transparent;
  border-right:50px solid transparent;
  border-bottom:50px solid red;
}

注:上述三角形为正三角形,如果想要倒三角形,那么将border-top的值设为50px solid red,其余的属性值相同。

 

17、1像素边框问题

物理像素:移动设备出厂时,不同设备自带的不同像素,也称硬件像素。逻辑像素:

解决方案:

媒体查询利用设备像素比缩放,设置小数像素

优点:简单,好理解。

.box{border:1px solid #333}
@media screen and (-webkit-min-device-pixel-ratio:2){
  .box{border:1px solid #333}
}
@media screen and (-webkit-min-device-pixel-radio:3){
  .border{border:0.333333px solid #333}
}

设置border-image方案

缺点:需要制作图片,圆角可能会出现模糊。

.border-image-1px{
  border-width:1px 0px;
  -webkit-border-image:url("border.png")2 0 strech;
  border-image:url("border.png")2 0 stretch;
}

border-width:指定边框的宽度,可以设定四个值,分别为上右下左top right bottom left。

优点是没有圆角问题。缺点是颜色不好控制。

.box{
  -webkit-box-shadow:0 1px 1px -1px rgba(0,0,0,.5);
}

参数:水平阴影位置,垂直阴影位置,模糊距离,阴影尺寸,阴影颜色,将外部阴影改为内部阴影。

transform:scale(0.5)方案(推荐):

以上的方案,思想其实都是将1px缩小为0.5px来展示,然而0.5px并不是所有的设备或浏览器都支持。其实1像素问题的产生基本发生在设置边框或分割线的时候,场景并不覆盖全局样式,因此,直接缩放需要设置的元素,才是我们真正需求的。transform就可以实现。

设置height:1px,根据媒体查询结合transform缩放为相应的尺寸

.box{
  height:1px;
  background:#333;
  -webkit-transform:scaleY(0.5);
  -webkit-transform-origin:0 0;
  overflow:hidden;
}

用: :after和: :before,设置border-bottom:1px solid #000;,然后缩放-webkit-transform:scaleY(0.5);可以实现两根边线的需求;

.box::after{
  content:"";
  width:100%;
  border-bottom:1px solid #000;
  transform:scaleY(0.5);
}

用: :after设置border:1px solid #000;width:200%;height:200%;然后缩放scaleY(0.5);优点可以实现圆角京东就是这么实现的,缺点是按钮添加active比较麻烦。

.div::after {
  content: '';
  width: 200%;
  height: 200%;
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid #bfbfbf;
  border-radius: 4px;
  -webkit-transform: scale(0.5,0.5);
  transform: scale(0.5,0.5);
  -webkit-transform-origin: top left;
}

18、水平垂直居中

A:水平居中

a、行内元素:给父元素设置text-align:center,即可实现行内元素水平居中

b、块级元素:该元素设置 margin:0 auto即可.

c、若子元素包含 float:left 属性, 为了让子元素水平居中, 则可让父元素宽度设置为fit-content,并且配合margin, 作如下设置:

.parent{
     width: -moz-fit-content;
   width: -webkit-fit-content;
   width:fit-content;
   margin:0auto;
}

注:fit-content是CSS3中给width属性新加的一个属性值,它配合margin可以轻松实现水平居中, 目前只支持Chrome 和 Firefox浏览器.

d、使用flex 2012年版本布局, 可以轻松的实现水平居中, 子元素设置如下:

.son{
  display: flex;
  justify-content: center;
}

e、使用flex 2009年版本, 父元素display: box;box-pack: center;如下设置:

.parent {
  display: -webkit-box;
  -webkit-box-orient: horizontal;
  -webkit-box-pack: center;
  display: -moz-box;
  -moz-box-orient: horizontal;
  -moz-box-pack: center;
  display: -o-box;
    -o-box-orient: horizontal;
    -o-box-pack: center;
    display: -ms-box;
    -ms-box-orient: horizontal;
    -ms-box-pack: center;
    display: box;
    box-orient: horizontal;
    box-pack: center;
}

f、使用CSS3中新增的transform属性, 子元素设置如下:

.son{
  position:absolute;
    left:50%;
    transform:translate(-50%,0);
}

g、使用绝对定位方式, 以及负值的margin-left, 子元素设置如下:

.son{
  position:absolute;
  width:固定;
  left:50%;
  margin-left:-0.5宽度;
}

h、使用绝对定位方式, 以及left:0;right:0;margin:0 auto; 子元素设置如下

.son{
  position:absolute;
  width:固定;
  left:0;
  right:0;
  margin:0 auto;
}

B:垂直居中

单行文本

1) 若元素是单行文本, 则可设置 line-height 等于父元素高度

行内块级元素

2) 若元素是行内块级元素, 基本思想是使用display: inline-block, vertical-align: middle和一个伪元素让内容块处于容器中央.

.parent::after, .son{
  display:inline-block;
  vertical-align:middle;
}
.parent::after{
  content:'';
  height:100%;
}

这是一种很流行的方法, 也适应IE7.

元素高度不定

3) 可用vertical-align属性, 而vertical-align只有在父层为 td 或者 th 时, 才会生效, 对于其他块级元素, 例如 div、p 等, 默认情况是不支持的. 为了使用vertical-align, 我们需要设置父元素display:table, 子元素 display:table-cell;vertical-align:middle;

优点

元素高度可以动态改变, 不需再CSS中定义, 如果父元素没有足够空间时, 该元素内容也不会被截断.

缺点

IE6~7, 甚至IE8 beta中无效.

4) 可用Flex 2012版, 这是CSS布局未来的趋势. Flexbox是CSS3新增属性, 设计初衷是为了解决像垂直居中这样的常见布局问题. 相关的文章如《弹性盒模型Flex指南

父元素做如下设置即可保证子元素垂直居中:

.parent {
display: flex;
align-items: center;
}

优点

  • 内容块的宽高任意, 优雅的溢出.
  • 可用于更复杂高级的布局技术中.

缺点

  • IE8/IE9不支持
  • 需要浏览器厂商前缀
  • 渲染上可能会有一些问题

5) 使用flex 2009版.

.parent {
    display: box;
    box-orient: vertical;
    box-pack: center;
}

优点

实现简单, 扩展性强

缺点

兼容性差, 不支持IE

6) 可用transform , 设置父元素相对定位(position:relative), 子元素如下css样式:

.son{
  position:absolute;
  top:50%;
  -webkit-transform: translate(-50%,-50%);  
  -ms-transform: translate(-50%,-50%);
  transform: translate(-50%,-50%);
}

优点

代码量少

缺点

IE8不支持, 属性需要追加浏览器厂商前缀, 可能干扰其他 transform 效果, 某些情形下会出现文本或元素边界渲染模糊的现象.

元素高度固定

7) 设置父元素相对定位(position:relative), 子元素如下css样式:

.son{
  position:absolute;
  top:50%;
  height:固定;
  margin-top:-0.5高度;
}

优点

适用于所有浏览器.

缺点

父元素空间不够时, 子元素可能不可见(当浏览器窗口缩小时,滚动条不出现时).如果子元素设置了overflow:auto, 则高度不够时, 会出现滚动条.

8) 设置父元素相对定位(position:relative), 子元素如下css样式:

.son{
  position:absolute;
  height:固定;
  top:0;
  bottom:0;
  margin:auto 0;
}

优点

简单

缺点

没有足够空间时, 子元素会被截断, 但不会有滚动条.

总结

水平居中较为简单, 共提供了8种方法, 一般情况下 text-align:center,marin:0 auto; 足矣

  •  text-align:center;
  •  margin:0 auto;
  •  width:fit-content;
  •  flex
  • 盒模型
  •  transform
  • ⑦⑧两种不同的绝对定位方法

垂直居中, 共提供了8种方法.

  • 单行文本, line-height
  • 行内块级元素, 使用 display: inline-block, vertical-align: middle; 加上伪元素辅助实现
  •  vertical-align
  •  flex
  • 盒模型
  •  transform
  • ⑦⑧两种不同的绝对定位方法

19、一行居中,多行居左

html内容:
<div><span>我是多行文字。我是多行文字。我是多行文字。我是多行文字。我是多行文字。我是多行文字。我是多行文字。我是多行文字。我是多行文字。我是多行文字。</span></div>
<div><span>我是一行文字</span></div>

css内容:
div{text-align: center;}
div span{display: inline-block;text-align: left;}

20、如何实现左右等高布局

html代码:
<div class="layout">
<div class="layout left">left</div>
<div class="layout right">center</div>
</div>

css代码:

.layout{
display: table;
width: 100%;
}
.layout div{
display: table-cell;
}
.layout .left{
width: 50%;
height: 200px;
background: red;
}
.layout .right{
width: 50%;
background: yellow;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值