20200928前端面经

1. 用过canvas吗,描述一下;和svg的区别

  • canvas基础知识

    <canvas id="mycanvas" width="150" height="150"></canvas>
    // canvas标签只有width和height两个属性,不设置的话默认300*150
    

    给canvas设置宽高要用width、height属性,而不是css,否则图形会变形,(css中设置宽高,不是讲修改画布宽高,而是将300*150的画布拉伸了)

    // index.js
    let painting = () => {
      let drawing = document.getElementById('canvas');
      if(drawing.getContext) {
        let pen= drawing.getContext('2d'); // 声明画笔
        pen.moveTo(10, 10); // 起点
        pen.lineTo(200, 100); // 终点
        pen.lineWidth = 2; // 笔触宽度
        pen.strokeStyle = '#098766';
        // 绘制
        pen.stroke();
      }
    }
    painting();
    
  • canvas应用–绘制图片

    // 平铺图片
    let pattenImg = () => {
      let patcanvas = document.getElementById('imgcan');
      let img = document.createElement('img')
      img.src = './img/pattenimg.jpeg' // 获取到图片
      if(patcanvas.getContext) {
        let patctx = patcanvas.getContext('2d');
        let pat = patctx.createPattern(img, 'repeat') // 创建图片pattern
        patctx.rect(0,0,1000,500); // 画一个矩形
        patctx.fillStyle=pat; // 用图片pattern来设置填充样式
        patctx.fill(); // 填充
        // patctx.drawImage(img, 200, 200); // 这个是单纯的画一张图片
      }
    }
    pattenImg();
    
  • canvas和svg的区别
    svg生成的每一个图形都是独立的元素,是矢量图可以放大缩小不失真
    canvas生成的是一个整体的画布,是位图,会失真

2. 图片上传到服务器、文件上传到服务器

ajax formdata上传
https://blog.csdn.net/lijia_1983370657/article/details/80489979

  1. 转成base64后再上传:
    H5新特性 readAsDataURL 可以将文件转base64格式

3. http跨域

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域
解决:

  1. PHP端修改header(XHR2方式)
    在php接口脚本中加入以下两句即可:
    header(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
    header(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
  2. 代理:例如www.xxx.com/index.html需要调用www.xxx.com/server.php,可以写一个接口www.xxx.com/server.php,由这个接口在后端去调用www.xxx.com/server.php并拿到返回值,然后再返回给index.html,这就是一个代理的模式。相当于绕过了浏览器端,自然就不存在跨域问题

4. promise和async、await的区别

都是异步编程的解决办法,都是非阻塞式的
async是基于promise实现的,用async声明的函数返回一个隐式promise,但是async解决了Promise的then链式回调繁琐问题,使代码更简洁易懂,减少中间变量。

5. 深浅拷贝

https://www.cnblogs.com/secretAngel/p/10188716.html

  • js的数据类型分为
    基本数据类型:Number, String, Boolean, Null, Undefined
    引用数据类型(对象数据)深拷贝和浅拷贝只是针对于引用数据类型(Object, Array)

基本数据类型直接存放在stack中,而引用数据类型是存放在堆内存heap中,变量是保存在栈内存中一个指向堆内存中对象内容的指针(引用地址)
在这里插入图片描述

浅拷贝:

在定义一个对象或数组时,变量存放的只是一个地址。当我们使用对象拷贝时,传递的只是一个地址。因此子对象在访问该属性时,会根据地址回溯到父对象指向的堆内存中,即父子对象发生了关联,两者的属性值会指向同一内存空间。

深拷贝:

不希望父子对象之间产生关联,既然属性值类型是数组和或象时只会传址,那么我们就用递归来解决这个问题,把父对象中所有属于对象的属性类型都遍历赋给子对象即可。
深拷贝的方法:

  • 递归

    let deepCopy = (origin) => {
      let result = Array.isArray(origin) ? [] : {}
      for(item in origin) {
        if(typeof(origin[item]) == 'object') {
          result[item] = deepCopy(origin[item])
        }else{
          result[item] = origin[item]
          console.log(origin[item])
        }
      }
      return result
    }
    
  • […arr]和Array.from() 第一层是深拷贝,但如果arr中有子数组,那么就只是浅拷贝。

  • Object.assign(目标对象,被拷贝对象)对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝

  • JSON.stringify() + JSON.parse() 深拷贝

6. addeventlistener和onclick的区别

  • onclick只能指向一个function,多次指向只会执行最后一个,前面的均被覆盖掉。
  • addeventlistener可以多次绑定事件,而不会覆盖之前绑定的处理程序并且按照顺序执行。另外,支持控制listener的触发阶段(捕获/冒泡),两个阶段都是通过addEventListener最后一个参数设置为false(默认值,表示事件冒泡)或者true(表示事件捕获)来切换

7. js中获取元素的几种方式

  • document.getElementById(‘id’); // 返回一个元素/null
  • document.getElementsByClassName(‘classname’); // 返回HTMLCollection/HTMLCollection [ ]
  • documnet.getElementsByTagName(‘tagname’); // 同classname

HTML Collection动态对象是类数组对象,可以用数字下标取元素,但不可以用数组的方法(foreach)。

  • document.getElementsByName(‘name’); // 同classname
  • document.querySelector(’.classname’); // 选择器,返回第一个符合的元素/null
  • document.querySelectorAll(’.classname’); // 选择器,返回NodeList []
  • document.documentElement; // 返回HTML标签
  • document.body; // 返回body标签

8. 日历组件的实现

9. vuex

storage、mutation(唯一可以改变状态的方法)

  1. vuex存的是状态,存在内存中,用于组件间传值,刷新存储值丢失
  2. 本地存储(localstorage、sessionstorage)存的本地文件,存在本地缓存中,主要用于页面间传值,刷新存储值不丢失

10. css的滤镜功能

filter 对图片的处理效果,例如灰度(greyscale),模糊(blur),饱和,老照片
https://www.cnblogs.com/mmzuo-798/p/6237010.html

11. es6

const\let
() => {}
for … in 遍历对象的属性
class

12. 权限管理

通过导航守卫做权限管理(全局 beforeEach,组件内 beforeRouteEnter)

methods: {
	onSubmit() {
		this.$axois.post('/api/users', {
			name: this.name,
			pwd: this.pwd
		}).then(res => {
			if(res.data.state === 0) {
				console.log('success');
				let token = res.data.token
				localStorage.setItem('token',JSON.stringify(token))
				localStorage.setItem('role',JSON.stringify('xxadmin'))
				this.$router.posh('/home');
			}else{...}
		})
	}
},
beforeRouteEnter (to, from, next) {
	// 不能用this,需要单独重新引入axois
	axois.get('/api/users').then(
		res => {
			if(res.data.status === 0) { // loged
				next(
					vm => {
						vm.$store.commit('自定义mutation', {
							name: res.data.data.name
						})
					}
				)
			}
		}
	)
}

13. 上传文件

<template>
  <div>
    <input type="text" v-model="loginForm.username" placeholder="用户名"/>
    <input type="text" v-model="loginForm.password" placeholder="密码"/>
    <button @click="login">登录</button>
  </div>
</template>
 
<script>
import { mapMutations } from 'vuex';
export default {
  data () {
    return {
      loginForm: {
        username: '',
        password: ''
      }
    };
  },
 
  methods: {
    ...mapMutations(['changeLogin']),
    login () {
      let _this = this;
      if (this.loginForm.username === '' || this.loginForm.password === '') {
        alert('账号或密码不能为空');
      } else {
        this.axios({
          method: 'post',
          url: '/user/login',
          data: _this.loginForm
        }).then(res => {
          console.log(res.data);
          _this.userToken = 'Bearer ' + res.data.data.body.token;
          // 将用户token保存到vuex中
          _this.changeLogin({ Authorization: _this.userToken });
          _this.$router.push('/home');
          alert('登陆成功');
        }).catch(error => {
          alert('账号或密码错误');
          console.log(error);
        });
      }
    }
  }
};
</script>

算法:

  1. 数组去重

    // 方法一
    let eee = [ 2, 3, 'ss', 4, 2, 'ss']
    let unique = (originalArr) => {
      let temp = []
      originalArr.forEach((item,index) => {
        if(temp.indexOf(item) === -1) {
          temp.push(item)
        }
      })
      return temp
    }
    console.log(unique(eee))
    // 方法二
    let uniqueArr = [...new Set(originalArr)];
    console.log(uniqueArr);
    
  2. 快速创建1-100的数组:

    console.log(Array.from(Array(100), (v,k) => k+1));
    
  3. 排序
    快速排序的复杂度和原理
    归并排序
    二分排序
    答案都是自己整理的,有错误的话欢迎指出

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值