前端内容的总结

一、HTML篇

1、简述一下你对HTML语义化的理解?

用正确的标签做正确的事情
    html语义化让页面的内容结构化,让结构更加的清晰,便于对浏览器、搜索引擎的解析;更容易阅读;
    搜素引擎的爬虫也依赖于html标记来确定上下文和各个关键字的权重,利于SEO;便于阅读源代码的人的阅读维护理解。
复制代码

2、标签上alt和title属性的区别

alt是给搜索引擎识别的,是图片无法显示时的替代文本
title是额外信息,就是给访问浏览器的人看的。当鼠标放在文字或者图片上时有title文字显示,在IE浏
览器中alt起到了title的作用。
在定义img对象的时候,将alt和title属性写全,就可以保证在任何的浏览器中都可以使用
复制代码

3、iframe的优缺点

iframen能够将另一个html页面嵌入到当前的页面。
iframe的优点:
.解决加载缓慢的第三方内容如图标和广告等的加载问题
.并行加载脚本
缺点:
.inframe加载会阻塞主页面的onload事件
.即使内容为空也需要加载时间
复制代码

4、herf和src?

href是指定网络资源的位置,目的不是为了引用资源,而是为
了建立联系,让当前标签能够链接到目标地址

src是指向外部资源的位置,指向的内容将会应用到文档中当前标签的位置。

两者的区别:
1、请求资源的类型不一样:herf指向网络资源所在的位置,
建立和当前元素或者当前文档之间的联系。
在请求是src资源的时候会将其指定的资源下载到文档中,
比如js脚本,img图片
2、作用结果不同:herf用于文档和资源之间建立联系;src用于替换内容
3、浏览器的解析方式不一样:当浏览器解析到src,会暂停其
他资源的下载和处理,直到将该资源加载、编译执行完成。
复制代码

5、为什么要将js放在html的底部,而不是头部?

因为浏览器加载完js文件之后就会去执行,这个时候如果js文
件中有对DOM的操作,DOM可能还未加载完毕,
这个时候就会导致错误的产生。
复制代码

6、解决跨域的问题

什么是跨域请求?
*在前端开发编码过程中,常见的html标签如a标签,from标签,img标签,link标签,iframe标签以及ajax操作,
都可以指向一个资源地址,也可以说是像一个地址请求资源,那么说到这里请求就分为同域请求和跨域请求,
所谓的跨域就是请求所在的域和请求的资源所在的域不一样(所谓的域就是指协议、域名、端口号,如果有
一个不一致就叫做跨域)
*同源策略是浏览器的核心基础安全策略,同源策略是用来防御来自非法的攻击,但我们不能
因为防御非法攻击就将所有的跨域都拦截掉
*在现代前端开发中,我们经常需要第三方的服务接口,随着专业划分共的出现,
有很多信息服务商为前端开发者提供各类接口,这种情况下就需要跨域请求
(这种前端接口服务很多是采用cors方式来解决跨域的问题)
*还有一类是前后端分离,前后端不在一个域内,于是也要实现跨域请求
解决方案:
1、jsonp:
原理:Ajax存在跨域安全问题但是script标签不存在这类问题,于是有人根据这个特性找到解决方案
复制代码
     <script>
       localFunction=function(data){
        console.log(data)
       }
    </script>
    <script src="http://localhost:3000/remote.php?callback=localFunction">

    </script>
复制代码
<?php
header('Content-type:application/json');
$callbackFunction = htmlspecialchars($_GET['callback']);
$data = 'data heha';
echo $callbackFunction.'('.$data.')';
复制代码
其实就是用回调函数来接收参数嘛
2、cors(跨域资源共享)
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器发出XMLhttprequest请求,从而克服了ajax请求只能同源使用的限制
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的
AJAX通信没有差别,代码完全一样
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
3、反向代理:
什么是反向代理:
反向代理服务器架设在服务器端,通过缓冲经常被请求的页面来缓解服务器的工作量,将客户机请求转发给内部网络上的目标服务器;并将从服务器上得到的结果返回给客户端,此时代理服务器和目标服务器表现为一个服务器。
目前web网站使用反向代理,除了可以防止外网对内网服务器的恶性攻击、缓存以减少服务器的压力和访问安全控制之外,还可以进行负载均衡,将用户请求分配给多个服务器
复制代码

二、CSS篇

1、介绍CSS盒模型

盒模型:margin(外边距)、border(边线)、padding(内边距)、content(内容)

2、CSS选择器优先级

!important > 行内(内联)样式(比重1000) > ID选择器(100) > 类选择器(10) > 标签选择器(比重1) > 通配符 > 继承 > 浏览器的默认样式

3、水平垂直居中的几种方式:

单行文本(行内元素):line-height:height;(实现高度居中),text-align:center(水平居中)
图片:vertical-aline:middle(垂直居中);(但是前提是高度要设置为100%)
利用外边距:

 <style>
       .father{
           width: 400px;
           height: 400px;
           background-color: azure;
           overflow: hidden;
           /* 开启BFC */
       }
       .son{
           width: 200px;
           height: 200px;
           background-color: red;
           margin-top:50%;
           margin-left:50%;
           transform: translate(-50%,-50%);
           
       }
   </style>
复制代码
<body>
   <div class="father">
       <div class="son"></div>
   </div>
</body>
复制代码

除了用外边距,加上BFC(消除外边距重叠的问题)之外

还可以利用绝对定位和相对定位,再利用外边距和平移

<style>
       .father{
           width: 400px;
           height: 400px;
           background-color: azure;
           position: relative;
       }
       .son{
           width: 200px;
           height: 200px;
           background-color: red;
           position: absolute;
           top:50%;
           left:50%;
           transform: translate(-50%,-50%);
           
       }
   </style>
复制代码

在相对定位和绝对定位下,子元素在绝对定位下让上下左右都是0,然后再加上margin:auto即可实现水平垂直居中

<style>
       .father{
           width: 400px;
           height: 400px;
           background-color: azure;
           position: relative;
       }
       .son{
           width: 200px;
           height: 200px;
           background-color: red;
           position: absolute;
           top:0;
           left:0;
           right:0;
           bottom: 0;
           margin: auto;
       }
   </style>
复制代码

使用flex布局

<style>
        .father{
            width: 400px;
            height: 400px;
            background-color: azure;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .son{
            width: 200px;
            height: 200px;
            background-color: red;
        }
    </style>
复制代码

4、简单说一下link和@import的区别

link是html标签,定义与外部资源的关系,最常用的用于是链接样式表(接入管理样式的CSS文件);
@import是属于css的范畴(低版本浏览器可能不支持),用于从其他样式表导入样式规则,示例:

@import 'custom.css';
复制代码

link引入css时,在页面载入时同时加载,@import需要在页面完全载入以后才能加载

5、rgba和opacity的透明效果有什么不同

opacity:子元素会继承父元素的opacity属性
rgba:而rgba设置的子元素不会继承父元素的透明属性

6、display:none和visibility:hidden的区别?

display:none:隐藏对应的元素,在文档布局中不再给他分配空间,他各边的元素会收拢

visibility:hidden:隐藏对应的元素,但是在文档中还是给他分配了空间

7、position的值:

relative:相对于自己原本的位置进行定位;如果有覆盖,则他在上面,并没有脱离文档流
absolute:想对于最近的开启了相对定位的祖先元素进行定位,脱离了文档流
fixed:绝对定位;相对于浏览器窗口进行定位

8、常见的兼容性的问题

浏览器的margin和padding不同,加一个全局样式*{margin:0;padding:0}

9、提交表单

1)一般的表单提交通过type=submit实现,input type=’submit’,浏览器显示为button按钮,通过点击这个按钮提交表单数据跳转到action的路径。

    <body>
   <form action="url.do" method="post">
       <input type="text" name="name">
       <input type="text" name="age">
       <input type="submit" value="提交">
   </form>
   </body>
复制代码

三、js篇

1、js的数据类型

基本数据类型:number、string、boolen、null、undefined、symbol(es6新增)
引用类型:object
typeof可以输出的类型:number、string、undefined、boolen、object、function
(在这里null会输出为object类型)

2、判断一个值是什么类型有几种方法?

1、typeof:

他对于数值、字符串、布尔值分别返回number、string、boolen,函数返回function,
undefined返回undefined,除此之外其他的都返回object,所以当返回值为object的时候
我们无法得知是数组还是对象或是其他的值
复制代码

2、instanceof运算符

他返回的是一个布尔值,他会检查右边的构造函数是不是在左侧对象的原型链上。instanceof运算符只能用于对象,不适用于原始值。
复制代码

可以利用上面的typeof和instanceof配合来实现类型判断

<script>
        function justify(value){
            let type = typeof(value)
            if(type!=='object'){
                return type
            }else if(value instanceof(Array)){
                return 'Array'
            }else if(value instanceof(Object)){
                return 'Object'
            }else{
                return 'null'
            }
        }
  
        console.log(justify([]))
    
        console.log(justify({}))
    </script>
复制代码

3、Object.prototype.toString()方法

console.log(Object.prototype.toString.call(2))
console.log(Object.prototype.toString.call({}))
function justify(value){
    let typestr = Object.prototype.toString.call(value)
    let type =  typestr.slice(8,-1)
    return type
}
console.log(justify([]))
复制代码

3、null和undefined的区别

null是什么都没有。

(1)undefined表示不存在这个变量或者是这个变量被声明了,但是并没有给他赋值。

(2)调用函数的时候,应该提供的参数没有提供,该参数等于undefined.

(3)对象没有赋值的属性,该属性的值为undefined

(4)函数没有返回值时,默认返回undefined

4、’==’和’===’的区别?

== 代表相同,=== 代表严格相同,
当进行双等号比较的时候:
先检查两个操作数据的数据类型是否相等,如果不相等先进行一次类型转换,转换成相同的类型后在进行比较
===进行比较的时候
如果类型不同,直接false
复制代码

5、eval是做什么的?

功能是把对应的字符串解析成JS代码并运行
应该避免使用eval

6、箭头函数有哪些特点

不需要function关键字来创建函数
自身没有this,要指向上一级函数的this指向(能够改变this指向)

7、var,let, const的区别?

一、var

1、var存在变量提升

   console.log(a)
   var a = 100;
复制代码

这种情况下,虽然显示打印了a,然后再声明的,但是由于var有变量提升的功能,并不会报错,而是输出undefined
相当于:

 var a ;
 console.log(a);
 a=100;
复制代码

2、var只有函数作用域,没有块级作用域,可以声明全局变量和局部变量(函数内的变量,只在函数内有效)

3、没有块级元素,也就决定了,var定义的变量可以跨块访问,但是不可以跨函数访问。
跨块级访问:

if(true){
        var a = 100;
        console.log(a)//100
    }
    console.log(a)//100
复制代码

跨函数访问:

function b(){
        var a = 100
        console.log(a)
    }
    b()//100
    console.log(a)//a is not defined
复制代码

4、var定义的变量可以重复定义,后定义会覆盖掉先定义的

二、let
1、let声明的变量有块级作用域,只能再块作用域内使用(既然不能跨块级作用域,那就更不能跨函数作用域了)
跨块级访问:

if(true){
    let a = 100;
    console.log(a)//100
}
console.log(a)//a is not defined
复制代码

2、不能进行变量提升

3、不能重复定义

4、有暂时性死区

三、const
const不仅有let的所有的性质,而且它定义的变量不可以修改,并且必须进行初始化,也就是const一般声明常量
但是定义的如果是对象可以更改它的属性

const a = {
    b:1
}
a.b = 2
console.log(a.b)
复制代码

8、暂时性死区

在块级作用域内使用let声明的变量就绑定在了这个区域,不再受到外部的影响,当然从外部也就访问不到他了。
ES6明确规定,如果区块中存在let和const命令,这个区块对于这两个命令声明的变量一开始就会形成封闭的区间,凡是在声明之前使用这个变量,就会报错
总之在代码块内,使用let声明变量之前,这个变量是不可用。这在语法中就叫做’暂时性死区’

9、new操作符具体干了什么

1、创建空对象

2、设置原型链,让创建的空对象的__proto__指向构造函数的原型;

3、让构造函数的this指向创建的空对象(因为是这个空对象调用了函数,所以函数指向这个空对象),并且函数执行。

4、函数执行的返回结果如果是原始值,那么我们创建的实例就是我们创建的那个空的对象,但是如果返回值不是原始值,而是引用值(也就是object),那么我们创建的实例就是这个引用值object

// 是创建实例的过程
        // 1、创建一个空的对象
        let obj = new Object();
        // 2、设置原型链(表明这个对象是con的实例)
        obj.__proto__ = con.prototype;
        // 3、让con中的this指向实例obj,并且执行函数
        var result = con.call(obj)
        // 4、判断con的返回类型,如果是值类型,就让实例对象是我们
        // 创建的obj空对象,如果这个返回值是一个对象,那么我们创建的
        // 实例对象就是这个返回值
        if(typeof(result)=='object'){
            c = result
        }else{
            c = obj
        }
        console.log(result)
复制代码

10、对json的了解?

1、JSON是一种轻量级的数据交换的格式,它是基于js的一个子集。2、json有两种数据格式就是对象和数组,它是js的一个子集。3、常用的JSON就是将json转换为字符串,用JSON.stringify,字符串转换为对象JOSN.parse,目的就是替换掉麻烦的xml。

11、document.write和innerHTML的区别?

document.write将内容写入页面的内容流,会导致页面全部重绘
innerHTML将内容写入某个DOM节点,不会导致页面全部重绘

12、ajax的过程

1、创建XMLHttpRequest对象,也就是创建一个异步调用对象
2、然后初始化一个请求,包括请求方式,请求的url
3、发送请求
4、设置响应请求状态变化的函数,对不同的响应状态进行处理
5、在响应状态变化函数中,如果成功就得到数据

13、js的同源策略

所谓的同源就是协议、域名、端口一样,同源策略是一种约定,它是浏览器最核心也最基本的安全功能

14、介绍一下闭包和闭包的应用场景

闭包指的是有权访问另一个函数(F1)中变量的一个函数(F2),创建闭包的常用的方法就是在一个函数(F1)中创建另一个函数(F2),然后将创建的这个函数(F2)return出来,F2中携带着要访问的F1中的信息。这个F2就叫做闭包
闭包的用途:
一是:可以读取函数内部的变量
二是:让这些变量值始终在内存中
第二条也是一个缺点:闭包会常驻内存,增加内存是使用量,如果使用不当的话会导致内存泄漏

15、js内存的垃圾回收机制

  • 垃圾回收器会每隔一段时间找出不再使用的内存,然后将其释放
  • 一般使用的是标记清楚法,当变量进入环境的时候标记为进入环境,离开环境的时候标记为离开环境。垃圾回收器在运行的时候会给存储在内存中的所有变量打上标记,然后会去掉环境中变量和被环境中变量所引用的变量的标记,做完这些之后,仍然有标记的就是要删除的变量。
  • 还有引用计数法,在低版本的IE中是采用这种计数方法进行垃圾回收的,引用计数的策略是跟踪记录每个值被使用的次数,当声明一个变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加一,如果该变量的值变成了另外一个,这个值就减一,当这个值得引用次数变为0的时候,说明没有变量在使用,这个值没法被访问了,因此可以将其占有的空间收回,这样垃圾回收期会在运行的时候清理掉引用次数为0的值的空间。

16、原型链的面试题

1、Object并不是原型链的顶层,Object.prototype才是原型链的顶层,有:Object.prototype.prot=null
2、所有函数都是Fuction的实例(包括Function),Fuction.proto = Fuction.prototype
3、所有对象都是Object的实例(包括原型对象),Function.Prototype.proto=Object.Prototype

 <script>
    let p = Object.prototype.constructor.__proto__==Function.prototype
    console.log(p)//true
    let f =Function.__proto__===Function.prototype
    console.log(f)//true
    Function.prototype.__proto__===Object.prototype//true
    Object.prototype.__proto__===null//true
  </script>
复制代码

17、实现表单的异步提交

<!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>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
    <body>
        <div id="app">
            <form ref='su' method="get">
                用户名:<input type="text" name="username">
                密码:<input type="text" name="password">
                <button @click='cheakForm'>点我</button>
            </form>
                <button @click='cheakForm'>点我</button>
        </div>
        <script>
            // var su = document.getElementsByName('form1')
            // function cheakFrom(e){
            //     if(document.form1.username==''){
            //         alert('姓名不能为空')
            //     }
            //     if(document.form1.password.value.length<5||document.form1.password.value.length>11){
            //         alert('密码输入错误')
            //     }else{
            //         su.submit()
            //     }
            // }
            // vue提交表单
            let vm = new Vue({
                el:'#app',
                methods: {
                    cheakForm(e){
                     e.preventDefault();
                     setTimeout(()=>{
                        let p = this.$refs.su
                        p.submit()
                     },2000)
                    }
                },
            })

        </script>
    </body>
</html>
复制代码

18、深拷贝和浅拷贝

在js中,深拷贝和浅拷贝都只是针对引用类型,浅拷贝会对对象逐个依次拷贝,但是只是复制内存地址;而不是复制对象本身,拷贝的内容和原来的内容都是指向一个对象,一个发生变化另一个也会跟着变。深拷贝会复制一个一模一样的对象,copy对象和源对象一个发生变化不会影响另一个。

四、Vue篇

1、谈谈你对MVVM开发模式的理解?

M是model,V是view,VM是viewmodel

<!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>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
    //v层
   <div id="app">
        <h1>{{msg}}</h1>
   </div>
   
   <script>
       //vm层
       var vm = new Vue({
           el:'#app',
           data(){//M层
               return{
                msg:'hello world'
               }
           }
       })
   </script>
</body>
</html>
复制代码

Model代表数据模型,数据和业务逻辑都在Model层中定义
View代表UI层,负责数据的展示
ViewModel负责监听Model中的数据的变化并且控制视图的更新,处理用户的交互操作。
Model和View并无直接的联系,而是通过ViewModel来进行联系的,Model和ViewModel之间是有着双向数据绑定的联系的。因此当Model中的数据发生变化的时候就会触发ViewModel让它来控制View进行视图的更新,View中因为用户的交互操作而改变的数据也会在Model中同步
这就实现了Model和View中的数据同步,开发者只需要专注数据的维护就可以,不需要自己操作DOM

2、v-if和v-show有什么区别?

v-if是真正的条件渲染,会控制这个DOM节点的存在与否。因为他会确保在切换的过程中条件块内事件监听器和子组件适当的销毁和重建;v-if也是惰性的:如果在初始渲染的时候条件为假,则什么也不做一直到条件变为真是时,才开始渲染

v-show就比较简单,不管条件是否为真,元素总是会被渲染,并且只是简单地基于CSS中的’display’属性进行切换。

当我们需要经常切换的时候,使用v-show,更能节省性能的开销;当只需要一次显示或者隐藏的时候,使用v-if更加合理。

3、vuex的使用

vuex是专为vue.js应用程序开发的状态管理模式。就是管理多组件间的共享数据的。
核心是创建一个Store仓库。Store就是一个仓库,存储这应用中大部分的状态state。
(1)Vuex的状态的存储也是响应式的,当Vue组件从Store仓库中读取状态的时候,如果Store仓库中的状态发生了变化,那么组件也会相应的更新
(2)改变Store中的状态唯一的途径就是显式的提交(commit)mutation。这样我们可以方便的追踪状态的变化
Store中主要包括这几个模块

action:包裹mutations,因为commit(mutation)如果是异步的话,mutation接收两个参数(行为函数,数据),但是如果是异步操作,可能还没有返回数据,就没法commit,这里加一层action可以处理这些异步操作,当数据返回之后,在进行下一步mutation,但是action不能直接修改state(状态)。

mutation:可以直接改变state(状态),且必须是同步函数

state:基本数据,基本数据,定义了应用状态的数据结构

getter:从基本数据中派生的数据,允许组件从中获取数据

4、说说你对SPA单页面的理解,它的优缺点是什么?

SPA仅在web页面初始化的时候加载相应的Html、JavaScript和CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或者跳转;取而代之是路由机制实现Html内容的变化(组件的跳转),UI与用户的交互,避免页面的重载
优点:

用户的体验好,快;内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
对于服务器的压力比较小;
前后端分离,架构清晰;
复制代码

缺点:

初次加载的耗费的时间长,
前进后退由路由管理,不能使用浏览器的前进后退功能
SEO的难度大
复制代码

5、在v-bind中class和Style的动态绑定?

class可以通过对象语法和数组语法进行动态绑定

1、class的对象语法:

class可以通过绑定到对象中:如v-bind:class='{active:isactive,text:hasError}'
在vm中的data中,如果isactive的trueiness是真实的,那么.active的样式表就会被显示,同理如果hasError的trueiness是真的,那么.text样式表也会显示
复制代码
<!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>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <style>
        .active{
            height: 200px;
            width: 200px;
            background-color:red;
        }
        .text-danger{
         font-size: 50px;
        }
    </style>
</head>
<body>
    <div id="app"  v-bind:class="{active:isactive,text-danger:hasError}">
        hahh
    </div>
    <script>
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                    isactive:true,
                    hasError:true
                }
            },
        })
    </script>
</body>
</html>
复制代码

还可以将对象写在下面

<body>
    <div id="app"  v-bind:class="classObject">
        hahh
    </div>
    <script>
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                   classObject:{
                       active:true,
                       text-danger:true
                   }
                }
            },
        })
    </script>
</body>
复制代码

2、class的数组写法
可以将要展示的class样式表全部写道数组中

<body>
    <div id="app"  v-bind:class="[activeClass, errorClass]">
        hahh
    </div>
    <script>
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                    activeClass: 'active',
                    errorClass: 'text-danger'
                }
            },
        })
    </script>
</body>
复制代码

但是这样写在数组的的样式表全部都会展示,没有达到动态的效果,可以加上一个判定,如下:

<body>
    <div id="app"  v-bind:class="[isactive?activeClass:'', errorClass]">
        hahh
    </div>
    <script>
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                    activeClass: 'active',
                    errorClass: 'text-danger',
                    isactive:true
                }
            },
        })
    </script>
</body>
复制代码

正如上面的代码,如果isactive的真实性为真,那么activeClass对应的.active样式表就会显示。
还可以对象形式和数组形式混合

<body>
    <div id="app"  v-bind:class="[{active:isactive}, errorClass]">
        hahh
    </div>
    <script>
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                    errorClass: 'text-danger',
                    isactive:true
                }
            },
        })
    </script>
</body>
复制代码

用在组件中:

<body>
    <div id="app">
        <my-component class="baz boo"></my-component>
    </div>
    <script>
        Vue.component("my-component",{
            template:`
            <div class='foo bar'>hhhhhhh</div>
            `,
        })
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                    errorClass: 'text-danger',
                    isactive:true
                }
            },
          
        })
    </script>
</body>
复制代码

注意一点:因为Vue.component是全局注册,所以在任何新创建的vm根实例中都可以使用,子组件之间也是可以相互使用的。缺点是:将来你不再使用该组件了,但是他仍然包裹在项目中。这造成了用户下载的无谓的增加。

还可以局部注册组件:

<body>
    <div id="app">
        <my-component class="baz boo"></my-component>
    </div>
    <script>
        let MyComponent = {
            template:`
            <div class='foo bar'>hhhhhhh</div>
            `,
        }
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                    errorClass: 'text-danger',
                    isactive:true
                }
            },
            components:{
               'my-component':MyComponent
            }
          
        })
    </script>
</body>
复制代码

注意:局部注册的组件在其子组件中是不可用的
绑定style(内联样式)的对象写法:

<body>
    <div id="app" v-bind:style="basecase">
      hahh 
    </div>
    <script>
        let vm = new Vue({
            el:"#app",
            data() {
                return {
                  basecase:{
                    color: 'red',
                    fontSize: '50px'
                  } 
                }
            },
          
        })
    </script>
</body>
复制代码

6、Vue中的单向数据流

单向数据流只能从一个方向改变状态,在双向数据流中,Model(状态的合集)中可以修改自己或者其他Model的状态,用户的操作也可以修改状态。这使得改变一个状态可能触发一连串的状态的改变,使代码很难调试。
而我们平时说的双向数据绑定其实是Vue的语法糖,也就是说Vue在数据流方面既可以实现单项数据流也可以实现双向数据绑定

双向数据绑定就是在单向数据绑定的基础上给可输入的元素(input、textare等)添加chage(input)事件,来动态修改model和view,即通过触发($emit)父组件的事件来修改mv来达到mvvm的效果。而Vue组件间传递数据是单向的,即数据总是由父组件传递到子组件,子组件在其内部可以有自己维护的数据,但是它无权修改父组件传递给他的数据,当开发者尝试这么做的时候,Vue将会报错。因为当多个子组件依赖父组件中的某个数据的时候,假如可以子组件可以修改父组件数据的话,一个子组件变化会引起所有依赖这个数据的子组件发生变化,所以Vue不推荐子组件直接修改父组件的数据,直接修改会抛出错误

当你想要在子组件中修改props的时候,把这个子组件当成父组件在父组件中那么使用:
1、定义一个变量,用props中的数据去初始化它,然后再改变变量
2、定义一个计算属性,处理props中的值,并返回

7、Vue为什么需要异步更新机制

vue是组件化的更新,如果每次一发生变化对应的组件就发生变化的话,那么如果组件的多个数据发生修改的话,那么会引发频繁的更新。

8、Vue的响应式原理

默认在数据初始化的时候,会用Object.definePerty通过遍历对data中的每一层属性加上getter方法和setter方法。当初始化渲染的时候,render会从data中获取数据,然后就调用了getter方法,闭包中dep就会将数据发布给所有需要监听该数据的watcher,然后会依赖收集(收集当前组件的watcher)然后就notify派发给watcher通知变化,然后更新视图。如果data被修改的话,就会触发setter,setter就会通过dep来notify通知watcher去再次render渲染

9、Vue2.0对于响应式数据的实现有一些不足:

1、无法检测对象和数组属性的添加
2、无法检测通过索引改变数组的操作。
因为是通过Object.defineProperty只是添加了getter和setter方法,所以只能检测到数据的获取和修改,无法检测属性的添加。但是无法通过索引改变数组的这个锅可不是的Object.defineproperty的,Vue中实现了对数组的7个变异方法的响应式的。Object.defineProperty是可以检测到通过索引来改变数组的操作的。但是由于性能的问题,vue并没有对他实现响应式。

10、Vue中如何检测数组的变化:使用了函数劫持的方法,重写了数组的方法

用了__proto__来截取原型链,让检测的数据值(数组)指向重写方法,重写方法的实现是定义arraymethods(重写方法对象) = Object.create(Array.prototype),让重写方法对象(arraymethods)的__proto__指向Array的原型对像,那么这样arraymethods可以通过原型链访问到Array原型的方法,先是对Array原型上的方法进行保存(先存一份),然后再用def(封装了Object.prototype()方法进行函数劫持)对这些方法进行重写。如果数组中包括引用值,那么就会调用ObserveArray()深度观测数组中的每一项。

11、为何Vue采用异步渲染

先了解一下,再给data中的同一个值赋值两次,如果页面的渲染和数据的变化是同步的,那么数据一变化就会发生渲染,页面就会出现变化。然而由于Vue内部的异步渲染机制,实际上页面只会渲染一次,因为在调用watcher中会进行去重操作。
这些变化会被暂存起来,这些变化操作会被丢到异步的API,Promise.then的回调函数中(也就是弄个任务栈,把微任务和宏任务抛进去),等到所有的同步任务都执行完毕之后才会执行任务栈中的微任务和宏任务里的回调,最终将和同步代码里需要渲染的部分合并到一块一起渲染。

四、计算机网络

1、http和https的区别?

1、https协议需要ca申请证书,一般免费证书较少,因为需要一定的费用

2、http是超文本传输协议,信息是明文传输,https则具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的链接方式,用的端口也是不一样的,前者是80;后者是443端口

4、Https协议是由SSL+Http协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

https的工作流程:
可以简单的理解为:http+证书认证+加密+完整性保护

http协议的缺点:
1、通信使用明文,内容可能被窃听
2、通信双方的身份无法得到认证,身份可能遭遇伪装
3、无法验证报文的完整性

针对上述问题:https的改进措施:
1、加密:http协议通过SSl或者TLS协议将报文内容进行加密。
2、认证:通过值得信赖的第三方机构颁布的证书,即可确认双方的身份
3、完整性保护。

2、为什么说http协议是无状态协议?怎么解决http协议无状态?

http协议是一种无状态协议,协议自身不对请求和响应之间的通信状态进行保存,也就是对发送过来的请求和响应不做持久化的处理,把http协议设计的如此简单就是为了更快的处理大量的事务。
为了解决http协议不能保存通信状态的问题,引入了cookie(保存再客户端的数据)状态管理。cookie技术通过在请求和响应报文中加入Cookie信息来控制客户端的状态。Cookie会根据从服务端发送的响应报文的一个叫做Set-Cookie字段,来提醒客户端保存cookie。当下一次客户端再次发送请求的时候会连同cookie一起发送出去,服务器端发现客户端发送过来的Cookie后,会检查是哪个客户端发过来的链接请求,对比服务器上的记录,得到之前的信息。

3、url和uri的区别?

URI:统一资源标识符,用来唯一标识互联网中的一份资源
URL:统一资源定位符,我们访问的网站的网址就是url

4、http的报文组成

http,超文本传输协议。http报文说白了就是客户端和服务端通信的时候依据http协议,将传输的信息以文本的形式呈现,这个文本就是http报文。分为请求报文和响应报文。

image.png
http的请求报文:

请求行/响应行:
请求行由http动词,URL和http的协议版本组成,主要是反应对什么资源做什么操作。
响应行由http返回状态码,原因短语和http版本组成,呈现的服务端对这次请求的处理。通过响应行的信息我们可以得知这次请求是否成功,bug是出在client端还是server端,原因是什么。
首部字段:首部字段又叫做头域,相当于http报文的元数据,记录这次http报文的具体描述信息,比如时间,服务器域名等。
报文主体:
报文主体并不是每一个报文都有的,要看具体的报文是要做什么。报文主体返回的格式一般是XML或者是JSON格式。

5、TCP对应的应用层协议有哪些?UDP对应的应用层协议有哪些?

TCP对应的典型的应用层协议:
http协议:超文本传输协议;
FTP协议:文件传输协议;
SSH:远程登陆协议;
UDP对应的典型的应用层协议:
DNS:域名解析协议
TFTP:简单文本传输协议
SNMP:简单网络管理协议

6、ARQ协议?

ARQ协议,即自动重传请求,意思是如果发送方在发送了一段时间之后没有收到回执,它通常会重新发送。ARQ协议包括停止等待ARQ协议和连续ARQ协议。
(1)停止等待ARQ协议是指,在停止等待中如果接收端没有收到发送端发来的数据,接收端就不会发送确认回执。此时发送端会重新发送之前的数据。发送端会维护一个超时计时器。
(2)连续ARQ协议
连续ARQ协议是指,发送端维护一个窗口,窗口内可以有很多个分组,窗口的大小是窗口中分组的个数,凡是位于窗口内的数据会连续发送不必等待回执,等最后一个分组发送完毕,服务端会向客户端发送回执,如果中间有个分组没有发送成功,就会返回没有发送成功的前边一个分组的序列号,然后该序列后面的分组全部重新发送。

7、说一些TCP的流量控制?

流量控制是为了控制发送端发送数据的速率,保证接收端能将本应该接收到的所有的报文分组接收成功,否则会触发自动重传机制,造成资源的浪费。
流量控制的具体操作是:接收端会通知发送端自己能接受的数据的大小,于是发送端会发送不超过这个数据量的数据,这个大小就叫做窗口的大小,在TCP首部中专门有一个字段表示窗口的大小,越大表示网络的吞吐量越高。

8、说一下TCP的拥塞控制

如果在通信的时候立刻把大量的数据注入网络,可能引起网络阻塞,甚至是网络瘫痪,并且拥塞会导致丢包。TCP为了防止该问题的出现,采用了拥塞控制策略。
TCP的四种拥塞控制算法:
1、慢开始
2、拥塞避免
3、快重传
4、快恢复
一个拥塞控制算法一般包括上面的四个步骤:慢开始、拥塞避免算法、快重传算法、快恢复算法。

1)不同的慢启动算法逻辑有所不同,经典的算法如下:
1、链接建立好之后先初始化cwnd(拥塞窗口),表明可以传10个MSS(最大报文段)大小的数据。
2、每当收到一个ACK,cwnd就加一,那么一个往返之间cwnd就会翻倍,呈指数增长。
3、有一个上限,当cwnd超过上限就会进入拥塞避免算法。
2)拥塞避免算法
当cwnd增长到一个上限的时候,就会进入拥塞避免算法,拥塞避免算法下cwnd成线性增长,每经过一次往返时间就将拥塞窗口cwnd加1。而不是加倍,避免拥塞窗口增长过快的问题。
3)快重传算法
快重传主要用于丢包检测,以便能更快的重传数据包。更早的调整拥塞状态机的状态,从而达到持续升窗的目的
4)当检测到丢包的时候,TCP会触发快速重传并进入降窗状态,该状态下cwnd会通过快速恢复算法降到一个合理值。

9、网络协议层的缓存

缓存的分类:
强缓存和协商缓存
先来了解一下什么是缓存,缓存可以理解为资源的备份,当我们向服务器请求了资源以后,会拷贝一份保存在本地,下次请求的时候直接拿出来用。他与localstorage和cookie等本地存储不同,本地存储主要是存储数据记录,存储量小,更多的是为了操作方便。而缓存就是为了减少资源请求,多用于存储文件,一般存储量较大。
强缓存有:expires(是一个事件戳,当客户端再次发送请求的时候,会把客户端时间和这个时间戳进行对比,如果大于该事件戳就重新请求资源,如果小于时间戳就直接用缓存)。缺点:但是有缺点,发送请求时使用客户端的时间去对比,但是客户端的时间和服务端的时间快慢不一致,还有就是客户端的时间可以修改,所以不一定能满足预期。所以有了cache-control
、cache-control(cache-control的优先级更高,该字段是一个时间长度,单位是秒,表示该资源过多长时间后自动过期,当客户端请求资源的时候发现该资源还在有效期内那么就直接利用缓存,他不依赖客户端时间)
他的值有:
1、max-age、s-maxage
max-age和s-maxage都是主要字段,他们是数字,表示资源过多少秒之后过期。在浏览器中max-age和s-maxage都是有效的,但是,s-maxage的优先级更高。一般在代理服务器中只有s-maxage是有效的。可以通过设置max-age为0来实现只要客户端请求资源就会向服务器发送请求。
public和private:
设置了public表示可以被客户端和代理服务器缓存,如果是private则表示只能被客户端缓存。但是如果设置了s-maxage则表示可以被客户端和代理服务器同时缓存,就相当于开了public。
no-cache和no-store
no-cache表示的是不直接问浏览器资源的情况,而是向服务端发送请求验证资源是否更新(也就相当于是协商缓存)。no-store则更狠,直接不使用缓存策略,直接向服务器获取新的资源。
expires和cache-control都是先从浏览器获取缓存,如果没有过期,就获取缓存,然后返回200.如果cache-control设置了no-cache那么就会先向服务器发送请求,如果资源没有更新,那么使用缓存,返回304.
协商缓存:last-modified和etag
1、last-modified:
last-modified记录资源最后的修改时间,启用之后,请求资源后的响应头中会有个last-modified字段,用来记录资源的最后的修改时间。如果再次发送请求的时候,请求头中会带有if-modified-since字段,字段的值是之前last-modified的值。然后服务器会对比if-modified-since的值和对应的资源的最后修改时间是否一致,如果一致则表明资源没有改动过,直接使用缓存就可以,返回304。如果不一致则需要重新发送资源,返回200。
但是last-modified也是有缺点的,只要编辑了,不管内容是否真的发生变化,都会引发重新的请求资源,这本是缓存最需要解决的问题,导致了没有必要的请求。
2、etag
etag会根据资源的内容生成唯一的字符串,当请求资源之后响应中会带有etag唯一标识的字符串,当再次发送请求的时候请求头中会带有if-none-match字段,字段的值是etag中的值,当客户端发送请求后,服务器会根据资源的内容生成一个字符串,让新生成的字符串与if-none-match中的字符串进行比对,如果一致则表示资源没有更新,如果不一致,则表明资源发生了更新。但是这样增加了服务器的开销。

10csrf和怎么防止csrf?

csrf是跨域请求伪造,用户在访问信任网站的时候,点击了跨域的恶意链接,然后恶意链接获取用户未过期的cookie和session等,来访问信任的网站(如银行客户端等)来进行恶意的操作。
怎么防止csrf攻击?1、验证token值,因为token是有加密的,所以第三方恶意网站无法伪造。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享