前端面试题(一)

1.简述px、 rpx、em和 rem之间的区别?

px

px 是css中常见的单位。相对长度单位。
px:pixel,像素,屏幕上显示的最小单位,用于网页设计,直观方便。


rpx单位
rpx 是小程序常用的单位
rpx和px的换算:1px=2rpx

其实是微信对于rem的一种应用的规定,或者说一种设计的方案,官方上规定屏幕宽度为20rem,规定屏幕宽为750rpx。

所以在微信小程序中 1 rem=750/20rpx。

如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

em单位
em单位大小CSS 3中新增的一种相对长度单位。

首先它会找自身有没有font-size,没有的话找父元素的字体大小(font-size),一直往上寻找,直到找到为止。

无论是字体大小还是宽度高度用了em单位,那么其px大小等于往上找到的字体大小乘于自身的em大小。
比如html->div->p,p的大小如果div没有设置字体大小,那么就找html的字体大小,如果没有就获取html的默认字体大小。(默认字体根据浏览器的不同或有变化)
这样就实现了随着字体大小的变化,响应式地改变大小,适应屏幕大小。

浏览器默认的字号是16px。所有未经调整的浏览器都符合: 1em=16px。

那么12px=0.75em,10px=0.625em。为了简化font-size的换算,需要在css中的body选择器中声明Font-size=62.5%,这就使em值变为 16px*62.5%=10px, 这样12px=1.2em, 10px=1em, 也就是说只需要将你的原来的px数值除以10,然后换上em作为单位就可以了。

em的特点

  1. em的值并不是固定的;
  2. em会继承父级元素的字体大小。

因为这两个特点,所以我们用em的时候,需要注意三点:

  1. body选择器中声明Font-size=62.5%;
  2. 将你的原来的px数值除以10,然后换上em作为单位;
  3. 重新计算那些被放大的字体的em数值。避免字体大小的重复声明。

rem单位
rem是CSS 3中新增的一种相对长度单位。当使用rem单位时,

根节点< html>的字体大小(font-size)决定了rem的尺寸。
与em单位相比,rem单位的优势在于,只通过修改< html>的文字大小,就可以改变整个页面中的元素大小,使用起来更加方便。
即使html没有设置字体大小,也不会获取父元素的字体大小,而是获取html的字体大小。

小结

  • 我们可以根据不同的需求分别使用不同的单位
  • px是相对单位,像素级
  • rpx是小程序用的比较多
  • 说到响应式单位,一般指的rem和em

推荐给大家一个px,em,rem单位转换工具:PX to EM conversion made simple.

2.一个盒子不给 宽高 如何水平垂直居中?

2.1 div绝对定位水平垂直居中【margin:auto实现绝对定位元素的居中】

让其父元素相对定位,内部元素绝对定位,这里的父元素为body。

  原理:让未定义宽高的图片上下左右距离都为0.然后给一个margin自适应。可以想象成一个盒子,给了四个方向的相同的力,这样就会形成一种相对的均衡力量让其停留在中间位置了。

<style>
    img{
        position:absolute;
        top:0;
        bottom:0;
        left:0;
        right:0;
        margin: auto ;
    }
</style>

<body>
    <img src="img/20181008095016_59996.jpg" alt="">
</body>

2.2 通过设置内部元素绝对定位,给一个translate属性,让其在x轴和y轴进行平移。原理跟方法一相似。

 <style>
       .ided{
           position:absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
                     /* X负数向左平移    Y轴负数往上平移 */
            background-color: burlywood;
            width:200px;
            height:200px;
        
       }
       

    </style>
</head>
<body>
        <div class="ided"> </div>
</body>
</html>

2.3. 让父盒子为flex容器:

flex布局 justify-content: center;(水平居中)  align-items: center;(垂直居中)

    .box1{

        height: 100vh;

        width: 50%;

        background: #f3f300;

        display: flex;

        justify-content: center;

        align-items: center;

    }

    .box2{

        height: 300px;        /* 这里可以改变 */

        width: 300px;        /* 这里可以改变 */

        background-color: #6676FF;

    }

        <div class="box1">

            <div class="box2">这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字</div>

        </div>

2.4 display:table-cell 表格

    .box1{

        height: 100vh;

        width: 50%;

        background: #f3f300;

        display: table-cell;

        vertical-align: middle;

    }

    .box2{

        height: 300px;        /* 这里可以改变 */

        width: 300px;        /* 这里可以改变 */

        background-color: #6676FF;

        margin: 0 auto;

    }

        <div class="box1">

            <div class="box2">这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字,这是一段测试文字,

        这是一段测试文字,这是一段测试文字</div>

        </div>

3.在移动端h5中怎么实现1px的细线?

在移动端web开发中,UI设计稿中设置边框为1像素,前端在开发过程中如果出现border:1px,测试会发现在某些机型上,1px会比较粗,即是较经典的 移动端1px像素问题。

移动端h5做自适应时通常使用淘宝的flexible方案,在处理手机1px边线通常边线宽高为200%,之后通过transform:scale(.5)来缩放,但是在安卓手机上的自带浏览器(低版本)中,会出现右边线、底边线不能正常显示,亲测手机(华为荣耀9play),通过上述css即可完美解决这一问题。【注意本次针对:使用淘宝flexible方案、ydui布局。其它暂不明确】

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, width=device-width">
		<title>移动端1px边框问题</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}

			ul,
			li {
				list-style: none;
			}

			.lines {
				width: 200px;
				margin: 0 auto;
			}

			.lines li {
				border: 1px solid #cccccc;
				height: 50px;
				line-height: 50px;
				text-align: center;
				border-radius: 13px;
				margin-top: 10px;
			}

			.hairlines {
				width: 200px;
				margin: 0 auto;
				border-radius: 3px;
			}

			.hairlines li {
				height: 50px;
				line-height: 50px;
				border: none;
				text-align: center;
				position: relative;
				margin-top: 10px;
			}

			.hairlines li:after {
				content: '';
				position: absolute;
				left: 0;
				top: 0;
				border: 1px solid #cccccc;
				border-radius: 26px;
				width: 200%;
				height: 200%;
				transform: scale(0.5);
				transform-origin: left top
			}
		</style>
	</head>
	<body>
		粗线
		<ul class="lines">
			<li>1</li>
			<li>2</li>
		</ul>
		细线
		<ul class="hairlines">
			<li>3</li>
			<li>4</li>
		</ul>
	</body>
</html>

4.Javascript面向对象的基本特征是什么?

封装、继承、多态.


5、下面的2个方法分别怎么调用?


class ClassName {
        test1(){}
        static test2(){}
}

第一个     test1()

第二个 ClassName.test2()

6.Vue2中父组件向子组件传参,有哪些方式可以实现。简述至少5种?

6.1、props传递数据

在父组件子组件添加自定义属性,挂载需要传递的数据,子组件用props来接受,接收方式也可以是数组,也可以是对象,子组件接收到数据之后,不能直接修改父组件的数据。会报错,所以当父组件重新渲染时,数据会被覆盖。如果子组件内要修改的话推荐使用 $emit

// Parent.vue 传送
<template>
    <child :msg="msg"></child>
</template>
​
// Child.vue 接收
export default {
  // 写法一 用数组接收
  props:['msg'],
  // 写法二 用对象接收,可以限定接收的数据类型、设置默认值、验证等
  props:{
      msg:{
          type:String,
          default:'这是默认数据'
      }
  },
  mounted(){
      console.log(this.msg)
  },
}

6.2 v-model

和 .sync 类似,可以实现将父组件传给子组件的数据为双向绑定,子组件通过 $emit 修改父组件的数据

// 父组件组件 这个是 v-model:obj="value"
<template>
  <div class="">
    <HelloWorld v-model:obj="value"></HelloWorld>
    {{ value }}
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {
      value: "我是Home里的数据 响应式的",
    };
  },
  components: { HelloWorld },
};
</script>
​
 // 子组件
<template>
  <input :value="obj" @input="handlerChange" />
</template>
<script>
export default {
  props: ["obj"],
  // 可以修改事件名,默认为 input
  model: {
    event: "updateValue",
  },
  methods: {
    handlerChange(e) {
      // 如果有上面的重命名就是这样
      this.$emit("updateValue", e.target.value);
    },
  },
};
</script>

6.3. ref

ref 如果在普通的DOM元素上,引用指向的就是该DOM元素;

如果在子组件上,引用的指向就是子组件实例,然后父组件就可以通过 ref 主动获取子组件的属性或者调用子组件的方法

// 父组件
<template>
  <div class="">
    <HelloWorld ref="child"></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {};
  },
  mounted() {
    const child = this.$refs.child;
    console.log(child.str); // 获取子组件的方法
    child.fn("调用了子组件的方法");
  },
  components: { HelloWorld },
};
</script>
​
// 子组件
<template>
  <input type="text" />
</template>
<script>
export default {
  data() {
    return {
      str: "我是数据",
    };
  },
  methods: {
    fn(e) {
      console.log(e);
    },
  },
};
</script>

6.4 $emit / v-on

在父组件中给子组件绑定自定义事件,然后调用需要的方法,然后在子组件中用 this.$emit 触发父组件的事件,第一个是事件名第二个是参数

// 父组件
<template>
  <div class="">
   <!-- v-on 简写 @ -->
    <HelloWorld @fn="fn"></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {};
  },
  mounted() {},
  methods: {
    fn(e) {
      console.log("子传父" + e);
    },
  },
  components: { HelloWorld },
};
</script>
​
// 子组件
<template>
  <input type="text" @blur="fn('我是子组件,可以传参数')" />
</template>
<script>
export default {
  data() {
    return {};
  },
  methods: {
  // 失去焦点发送
    fn(e) {
      this.$emit("fn", e);
    },
  },
};
</script>

6.5 $children / $parent的使用

$children:获取到一个包含所有子组件(不包含孙子组件)的 VueComponent 对象数组,可以直接拿到子组件中所有数据和方法等

$parent:获取到一个父节点的 VueComponent 对象,同样包含父节点中所有数据和方法等

// 父组件
<template>
  <div class="">
    <HelloWorld></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {
      name: "父组件数据",
    };
  },
  mounted() {
    this.$children[0].fn(); // 调用第一个子组件的方法
    console.log(this.$children[0].name); // 获取第一个子组件中的属性
  },
  methods: {
    fn() {
      console.log("父组件里的方法 s-z-h");
    },
  },
  components: { HelloWorld },
};
</script>
 
// 子组件
<template>
  <div>
    <input type="text" />
  </div>
</template>
<script>
export default {
  data() {
    return {
      name: "我是子里的数据",
    };
  },
  methods: {
    fn() {
      console.log("我是子组件方法");
    },
  },
  mounted() {
    this.$parent.fn(); // 调用父组件的方法
    console.log(this.$parent.name); // 获取父组件中的属性
  },
};
</script>

6.6 provide / inject 祖孙之间通信传值

provide / inject 为依赖注入,说是不推荐直接用于应用程序代码中,但是在一些插件或组件库里却是被常用,所以我觉得用也没啥,还挺好用的

provide:可以让我们指定想要提供给后代组件的数据或方法

inject:在任何后代组件中接收想要添加在这个组件上的数据或方法,不管组件嵌套多深都可以直接拿来用

要注意的是 provide 和 inject 传递的数据不是响应式的,也就是说用 inject 接收来数据后,provide 里的数据改变了,后代组件中的数据不会改变,除非传入的就是一个可监听的对象
 

// 父组件 Home
 <template>
  <div class="">
    <HelloWorld></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {
      val: "父组件数据",
    };
  },
  provide() {
    return {
      name: this.val, // data 的数据
      someMethod: this.someMethod, // methods 中的方法
    };
  },
  methods: {
    someMethod() {
      console.log("这是注入的方法");
    },
  },
  components: { HelloWorld },
};
</script>
// 子组件 HelloWorld
<template>
  <div>
    <input type="text" />
    <SunChild></SunChild>
  </div>
</template>
<script>
import SunChild from "./sun-child.vue";
export default {
  data() {
    return {};
  },
  inject: ["name", "someMethod"],
  mounted() {
    console.log(this.name);
    this.someMethod();
  },
  components: { SunChild },
};
</script>
// 孙组件SunChild 也可以拿数据
<script>
export default {
  data() {
    return {};
  },
  mounted() {},
  inject: ["name", "someMethod"],
  mounted() {
    console.log(this.name);
    this.someMethod();
  },
};
</script>

6.7 vuex通信

可以定义共享的数据源,在哪里都可以访问 安装配置 使用即可

// vuex 里定义共享的数据,在哪个组件都可以访问
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import vuexPersist from "vuex-persist";
export default new Vuex.Store({
  state: {
    data: 'vuex 的数据',
    a: 1,
    b: 2,
  },
  mutations: {},
  actions: {},
  modules: {},
  getters: {
    num(state) {
      return state.a + state.b
    }
  },
})
<template>
  <div class="">
    {{ data }}
    {{ num }}
  </div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
export default {
  data() {
    return {};
  },
  // 辅助函数
  computed: { ...mapState(["data"]), ...mapGetters(["num"]) },
  // 第二种 希望你会举一反三
  // computed: {
  //   data() {
  //     return this.$store.state.data;
  //   },
  // },
  components: {},
};
</script>

6.8 具名插槽+作用域插槽 slot

具名插槽是在父组件中通过slot属性,给插槽命名,在子组件中通过slot标签,根据定义好的名字填充到对应的位置。

作用域插槽是带数据的插槽,子组件提供给父组件的参数,父组件根据子组件传过来的插槽数据来进行不同的展现和填充内容。在标签中通过 v-slot="value" 来接受数据。
 

// 父组件
<template>
  <div class="">
    <HelloWorld>
      <template v-slot:a="value">
        <h2>{{ name }}</h2> // 这个是具名插槽
         <!--  value 是子组件传过来的数据 -->
        <h2>{{ value.value }}</h2> // 这个是作用域插槽
      </template>
    </HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
  data() {
    return {
      name: "具名插槽 slot插槽传数据 父传子",
    };
  },
  components: { HelloWorld },
};
</script>
 
 
// 子组件
<template>
  <div>
    <slot name="a" :value="value"></slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      value: "我是子组件数据 作用域插槽子传父 s-z-h",
    };
  },
  methods: {},
};
</script>

6.9  $root

$root 可以拿到 App.vue 里的数据和方法

// HelloWorld 子组件添加数据
<template>
  <div></div>
</template>
<script>
export default {
  data() {
    return {};
  },
  mounted() {
    // 写入根组件的数据
    this.$root.foo = 2;
  },
  methods: {},
};
</script>
 
// Home 父组件访问数据
<template>
  <div class="">
    <HelloWorld></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "../components/HelloWorld.vue";
export default {
    data() {
        return {};
    },
    mounted() {
        // 获取根组件的数据
        console.log(this.$root.foo);
    },
    components: { HelloWorld }
};
</script>

7.setTimeout和setlnterval哪一种做计时器更精准

setTimeout在规定时间后执行完某个操作就停止了,而setInterval则可以一直循环执行下去

这两种方法可能看起来很像,而且显示的结果也会很类似,只是两者的最大差别就是,setTimeout方法不会每隔5秒钟就运行一次showTime函数,它是在每次调用setTimeout后过5秒钟再去运行showTime函数。这意味着如果showTime函数的主体部分需要2秒钟运行完,那么整个函数则要每7秒钟才运行一次。而setInterval却没有被自己所调用的函数所束缚,它仅仅是简单地每隔一定时间就反复运行一次那个函数。

如果要求在每隔一个固定的时间间隔后就精确地运行某动作,那么最好使用setInterval,而如果不想因为连续调用产生互相干扰的问题,尤其是每次函数的调用需要繁重的计算以及很长的处理时间,那么最好使用setTimeout。

答案:以1秒为例,setInterval和setTimeout都会在异步模块运行,但是setInterval会每次都刚刚好1s钟的时候,将微任务队列的函数,交于任务队列进行执行。如果setInterval第一次1.004s的时候将任务推进队列,那么这时候setInterval的每次的误差会是在0.996s-1.01s内波动,而setTimeout每次的误差值都会大于1s。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,我无法提供具体的2024年前端面试题一百道,因为面试题的内容和形式可能会因公司、职位和行业而异。不过,我可以提供一些通用的前端面试题,以帮助您准备面试。 1. 请简述前端开发的主要技术栈包括哪些? 2. 请描述一下什么是HTML、CSS和JavaScript? 3. 请解释一下什么是响应式设计?如何在前端开发中实现响应式设计? 4. 请简述一下什么是前端框架,并列举几个常用的前端框架。 5. 请解释一下什么是Vue.js,并简述其核心概念和用法。 6. 请解释一下什么是React.js,并简述其核心概念和用法。 7. 请简述一下什么是Webpack,并解释其作用和用法。 8. 请解释一下什么是ES6,并列举一些ES6的新特性。 9. 请简述一下什么是前端性能优化,并列举一些优化技巧。 10. 请解释一下什么是HTTP/2,并简述其优点和缺点。 除了以上问题,您还可以准备一些更具体的问题,例如: 1. 请解释一下如何使用CSS选择器选择元素? 2. 请解释一下如何使用JavaScript操作DOM? 3. 请描述一下如何使用Vue.js实现一个简单的计数器组件。 4. 请解释一下如何使用React.js实现一个简单的表单组件。 5. 请描述一下如何使用Webpack进行代码拆分和优化。 6. 请解释一下什么是跨域问题,并简述如何解决跨域问题。 7. 请描述一下如何使用JavaScript进行异步编程,例如使用Promise和async/await。 8. 请解释一下什么是前端安全,并列举一些常见的安全问题及其解决方法。 希望以上信息对您有所帮助,祝面试成功!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值