前端——面试(熊猫优选)

1.Vue生命周期

  • beforeCreate —— 创建之前
    主要用来初始化事件和实例,希望在每个组件上增加一些特定的属性,可以采用这个钩子。
  • created —— 创建完成 首次拿到data
    该阶段实现了【数据劫持】,把【方法、计算属性】都挂在到了实例上。(不能获取到真实的 DOM 元素)可以在里边完成 ajax,不能操作 DOM。 如果没有指定结点 el,或者没有通过 vm.$mounted() 挂载,内部将默认渲染到一个内存中的节点。 然后判断是否有 template 模板选项,如果有将 template 编译到 render 函数中。 否则,将 el 外部的 HTML 作为 template 模板进行编译。
  • beforeMount —— 挂载之前
    在挂载之前会调用 render 函数方法,调用 render 但是一般不会增加业务逻辑。 如果在这个阶段创建了 vm.el ,则将其替换原来的 el 。
  • mounted —— 挂载之后 首次可以操作dom
    将挂载到真实 DOM 上,这个阶段可以操作 DOM。
  • beforeUpdate —— 更新之前
    当 data 被修改时,就会先调用 beforeUpdate。然后重新渲染虚拟 DOM 并把应用更新。
  • updated —— 更新之后
    更新完后,调用 updated 函数。
  • beforeDestroy —— 销毁之前
    当调用 vm.$destroy 函数时,先调用 beforeDestroy 函数,这个阶段会绑定销毁子组件以及事件监听器。
  • destroyed —— 销毁之后
    全部销毁完毕!

2.Computed和watch区别与使用场景

  • 区别
    • computed:计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
    • watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
  • 使用场景
    • Computed:计算属性,存在缓存。字符串和字符串反转,姓名案例 (计算属性:是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要message还没有发生改变,多次访问reversedMessage计算属性会立即返回之前的计算结果,而不必再次执行函数。)
      var vm = new Vue({
              
              
      	el: '#demo', 
      	data: {
              
               
      		firstName: 'Foo', 
      		lastName: 'Bar'
      	 }, 
      	computed: {
              
               
      		fullName: function () {
              
               
      			return this.firstName + ' ' + this.lastName
      		 } 
      	} 
      })
      
    • Watch:监听属性,当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
      var vm = new Vue({
              
              
      	el: '#demo', 
      	data: {
              
               
      		firstName: 'Foo', 
      		lastName: 'Bar', 
      		fullName: 'Foo Bar' 
      	}, 
      	watch: {
              
               
      		firstName: function (val) {
              
               
      			this.fullName = val + ' ' + this.lastName 
      		}, 
      		lastName: function (val) {
              
               
      			this.fullName = this.firstName + ' ' + val 
      		} 
      	} 
      })
      

3.组件中data为什么是函数而不是对象

  • 因为js的特性带来的,跟vue本身设计无关。js本身的面向对象编程也是基于原型链和构造函数,应该会注意原型链上添加一般都是一个函数方法而不会去添加一个对象。
  • 如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果
  • 组件中的data设置为一个函数,相当于每个组件实例都有自己的作用域,那么局部作用域中的数据改变是不会影响其他作用域的,也就是说每个组件相互独立,互不影响。这样就保证了组件的复用性和灵活性。

4.v-if和v-show区别?以及适用场景有哪些?

  • v-if: 相当于真正的条件渲染,当条件为假,元素不会被渲染。不是使用CSS来改变元素,而是操作DOM,动态的删除和添加元素
  • v-show :不管初始条件是什么,第一次的时候元素总被渲染。之后的切换相当于 display:none 和 display:block 的切换。
  • 适用场景
    • v-if : 适用于在运行时很少改变条件,不需要频繁切换条件的场景
    • v-show : v-show 则适用于需要非常频繁切换条件的场景。

5.Webpack

  • 四大核心概念
    • Entry
    • Ouput
    • devServer
    • Plugins
const path = require('path');
//2.引入webpack
const webpack = require('webpack');
//导入HTML插件
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    
    
    //入口
    entry:path.join(__dirname,'./src/main.js'),
    //出口
    output:{
    
    
        //输出路径
        path:path.join(__dirname,'./dist'),
        //打包后的文件名称
        filename:'bundle.js'
    },
//服务配置
    devServer:{
    
    
        open:true,//自动打开浏览器
        port:3000,//端口
        contentBase:'src',//托管根目录
        hot:true//hot比较麻烦,需要三步:1.启用热更新
    },
//插件配置
    plugins:[
        //3.new一个热更新的模块对象
        new webpack.HotModuleReplacementPlugin(),
        //创建一个在内存中生成HTML页面的插件
        new htmlWebpackPlugin({
    
    
            //指定模板页面,根据指定的页面路径,生成内存中的页面
            template:path.join(__dirname,'./src/index.html'),
            //指定生成页面的名称
            filename:'index.html'
        })
    ],
    module:{
    
    
        //配置所有的第三方加载器
        rules :[//匹配规则
            {
    
    test:/\.css$/,use:['style-loader','css-loader']},
            {
    
    test:/\.less$/,use:['style-loader','css-loader','less-loader']},
            {
    
    test:/\.scss$/,use:['style-loader','css-loader','sass-loader']},
           /* limit给定的值是图片的大小,单位是byte,
            图片大小<limit的值,不会转为base64格式字符串
            图片大小>=limit的值,会转为base64格式字符串*/
           /*
           图片的名称:前面有8为hash值(原本32位)-图片原本的名称.图片原本的后缀名
           name=[hash:8]-[name].[ext]
           */
           //处理图片
            {
    
    test:/\.(jpg|png|gif|jpeg|bmp)$/,use:'url-loader?limit=89796&name=[hash:8]-[name].[ext]'},

            //字体图标后缀名
            {
    
    test:/\.(eot|ttf|svg|woff|woff2)$/,use:'url-loader'},

            {
    
    test: /\.js$/,use:'babel-loader',exclude:/node_modules/}
        ]
    }
};

6.CSS

  • CSS动画:animation:动画名称 动画时间 运动曲线 何时开始
    @keyframes 动画名称 { }
  • 隐藏与显示一个元素
    • opacity=0:该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定一些事件,如 click 事件,那么点击该区域,也能触发点击事件的
    • visibility=hidden:该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已经绑定的事件
    • display=none:把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删除掉一样。
  • 可以继承的属性
    • 字体系列属性
      font:组合字体
      font-family:规定元素的字体系列
      font-weight:设置字体的粗细
      font-size:设置字体的尺寸
      font-style:定义字体的风格
      font-variant:设置小型大写字母的字体显示文本,这意味着所有的小写字母均会被转换为font-stretch:允许你使文字变宽或变窄。所有主流浏览器都不支持
      font-size-adjust:为某个元素规定一个 aspect 值,字体的小写字母 “x” 的高度与 “font-size” 高度之间的比率被称为一个字体的 aspect 值。这样就可以保持首选字体的 x-height。
    • 文本系列属性
      text-indent:文本缩进
      text-align:文本水平对齐
      line-height:行高
      word-spacing:增加或减少单词间的空白(即字间隔)
      letter-spacing:增加或减少字符间的空白(字符间距)
      text-transform:控制文本大小写
      direction:规定文本的书写方向
      color:文本颜色
    • 元素可见性:visibility
    • 表格布局属性:caption-side、border-collapse、border-spacing、empty-cells、table-layout
    • 列表属性:list-style-type、list-style-image、list-style-position、list-style
    • 生成内容属性:quotes
    • 光标属性:cursor
    • 页面样式属性:page、page-break-inside、windows、orphans
    • 声音样式属性:speak、speak-punctuation、speak-numeral、speak-header、 speech-rate、volume、voice-family、pitch、pitch-range、 stress、richness、、azimuth、elevation

7.JS

  • 设置一个闭包实现输出1,2,3
for (var i = 0; i < 4; i++) {
    
    
      console.log(i);
}
for (var i = 0; i < 4; i++) {
    
    
      setTimeout(function() {
    
    
         console.log(i);
      }, 1000);
 }
 for (var j = 0; j < 4; j++) {
    
    
      setTimeout((function(j) {
    
    
          return function() {
    
    
              console.log(j)
          }
      })(j),1000)
  }
for(var j = 0;j < 4;j++){
    
    
	(function(val) {
    
    
	    setTimeout(function(){
    
    
	        console.log(val)
	    },1000)
	})(j)
 }
//let块级作用域
for(let i=0;i<5;i++){
    
    
	setTimeout(function(){
    
    
	   console.log(i)
	},1000*i)
}
  • ES6新增
    ①let const
    ②函数扩展:箭头函数和rest参数
    ③class类的概念
    ④代理proxy
    ⑤新增数据类型symbol:声明独一无二的值
    ⑥Set:类似数组,成员唯一,无重复元素
    Map:类似对象,键不局限于字符串,可以是任意类型
    ⑦字符串扩展:
    repeat()函数,平铺指定字符串指定次数
    模板字符串:``,不使用+号拼接
    ⑧模块:import导入,export导出
    ⑨promise对象:异步编程的解决方案,解决回到地狱问题

  • 延迟加载JS

    • 通过script的标签async
      <script src="a.js"></script>
      <script src="b.js" async="async"></script>
      <script src="c.js"></script>
      async标签表示应该立即下载b.js,但是同时不妨碍浏览器下载其他资源,也就是不阻塞浏览器执行其他操作。但是会在下载结束后立即执行,同时会在windows的load事件前执行,所以会出现执行顺序被打乱的情况。所以不推荐使用。正常执行顺序 a.js =>b.js=>c.js,加入async的执行顺序a.js和c.js的顺序不变,但是b.js会在下载完毕后立即执行。
    • 通过script的标签defer
      <script src="a.js"></script>
      <script src="b.js" defer="defer"></script>
      <script src="c.js"></script>
      defer标签同async标签一样的地方是都不会阻塞页面的渲染加载。不同的在于defer是立即下载但是不会在下载完毕后就执行,而是等到html标签结束后才执行。不会打乱,而是会按照原有的顺序执行js。正常执行顺序 a.js =>b.js=>c.js,加入defer的执行顺序a.js =>c.js=>b.js。只是下载的时候相当于异步下载。
    • 动态添加:原理和前两种一样。
    (function(){
          
          
    	 var scriptEle = document.createElement("script");
    	 scriptEle.type = "text/javasctipt";
    	 scriptEle.async = true;
    	scriptEle.src="http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
    	 var x = document.getElementsByTagName("head")[0];
    	 x.insertBefore(scriptEle, x.firstChild); 
     })();
    
    • 通过setTimeout进行延迟加载
    <script src="" id="last"></script>
    <script>
    	var last = document.getElementById('last')
    		setTimeout(function(){
          
          
    			last.src = 'a.js'
    	}, 1000)
    </script> 
    
    • 我们都将script标签放在前面,防止阻塞。
    • Jquery的getScript()方法
    $.getScript("outer.js",function(){
          
          //回调函数,成功获取文件后执行的函数
    	console.log("脚本加载完成")
     });
    

8.GET和POST区别

  • get参数通过 url 传递,post 放在 request body 中。
  • get请求在url中传递的参数是有长度限制的,而 post 没有。
  • get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
  • get 请求只能进行 url 编码,而 post 支持多种编码方式
  • get 请求会浏览器主动 cache,而 post 支持多种编码方式。
  • get 请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留。
  • GET和POST 本质上就是 TCP 链接,并无差别。但是由于 HTTP 的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 GET 产生一个 TCP 数据包,发送一次请求,header和data会一起发送;POST 产生两个 TCP 数据包,发送两次请求,一次发送header ,返回100 continue,再发送data。

猜你喜欢

转载自blog.csdn.net/qq_44349849/article/details/114268425