1、vue的双向绑定原理是什么?里面的关键点在哪里?
2、实现水平垂直居中的方式?
3、常用伪元素有哪一些?
4、移动端如何适配不同屏幕尺寸?
5、本地存储有哪一些?他们三者有什么区别?
6、JS的数据类型?如何判断js的数据类型?
7、说一下ES6的新特性有哪些?
8、Let、const、var三者有什么区别?
9、数组去重有哪些办法?
ES6新增构造函数set,利用set具有天然去重功能
数组迭代
10、说一下深拷贝和浅拷贝,如何自己实现一个深拷贝?
11、Vue的生命周期有哪一些?说一下它们每个阶段做什么操作?
12、组件通讯方式有哪一些?
13、Vuex有几个属性及作用?
14、Vue的监听属性和计算属性有什么区别?
15、说一下防抖和节流。怎么实现?
16、Vue的导航守卫有哪一些?
17、你的登录拦截怎么实现的?
18、有用过图表吗?用的多吗?
19、闭包是什么?如何实现?
20、Vue2.0和vue3.0有什么区别?
21、Vue常用的指令有哪些?
22、v-If和v-show有什么区别?
23、v-for为什么要加一个key?
24、你是如何封装一个组件的?
25、有自己从0到1搭建过项目吗?
26、有用过uni-app吗?
27、你会写后台吗?有搞过服务端渲染吗?
28、说一下你项目中遇到的难点,如何解决?
29、Url到浏览器的一个过程有哪些步骤?
30、如何实现小程序的request封装及拦截?
31、在vue的项目应用中,不使用框架,怎么封装?
32、什么是Js原型?原型链是什么?
33、组件通讯方式有哪些?
34、用闭包的原理做过哪些?
35、作用域是什么?
36、操作数组的方式有哪些?
37、0.1 + 0.2 等于 0.3吗?为什么?如何解决?
38、keep-alive是什么?有哪几个生命周期阶段?
39、判断一个变量是否是数组,有哪些办法?
40、判断一个变量是否是对象,有哪些办法?
41、对象/数组常用方法有哪些?
42、创建一个空数组/空对象有哪些方式?
43、哪些遍历方式会改变原数组?
44、Set和Map各是什么?
45、介绍一下promise。
46、Promise通常会解决三种问题
(1)链式回调
(2)同时发起几个异步请求,谁先有结果就拿谁的
(3)发起多个请求,等到所有请求后再做下一步处理
这三种方式promise是怎么处理的?
47、如何改变一个函数a的上下文?
48、Call和replay有什么区别?
49、Evenbus是什么东西?
50、Vue中普通的生命周期大概有哪些?
51、父子组件生命周期执行顺序是怎么样的?
52、mixins有几个生命周期阶段?
53、弹性布局,一行两列,一列固定宽,如何实现?
54、Flex:1 包含哪三种属性
Vue的双向绑定是指数据的变化可以自动反映到视图上,同时视图的变化也可以自动更新到数据上。这种双向绑定的实现是Vue框架的核心特性之一。
Vue的双向绑定原理主要包括以下几个关键点:
数据劫持(Data Observation):Vue通过使用Object.defineProperty()方法来劫持(监听)数据对象的属性。当数据对象的属性被访问或修改时,Vue会触发相应的getter和setter方法。
响应式系统(Reactivity System):Vue通过响应式系统来追踪数据的变化。当数据对象的属性被修改时,Vue会通知相关的视图进行更新。
模板编译(Template Compilation):Vue使用模板编译器将Vue模板转换为渲染函数。在编译过程中,Vue会解析模板中的指令和表达式,并生成对应的渲染函数。
虚拟DOM(Virtual DOM):Vue使用虚拟DOM来提高渲染性能。当数据发生变化时,Vue会生成新的虚拟DOM,并与旧的虚拟DOM进行比较,找出需要更新的部分,然后只更新需要更新的部分。
数据绑定(Data Binding):Vue使用指令(如v-model)来实现数据的双向绑定。指令会将数据对象的属性与视图元素进行绑定,当数据发生变化时,视图会自动更新;当视图发生变化时,数据也会自动更新。
总结起来,Vue的双向绑定原理是通过数据劫持、响应式系统、模板编译、虚拟DOM和数据绑定等机制来实现的。这些机制相互配合,使得数据的变化可以自动反映到视图上,同时视图的变化也可以自动更新到数据上,从而实现了双向绑定的效果。
常用的伪元素有以下几种:
这些伪元素可以通过CSS的选择器来选择和样式化,它们可以用来在元素的特定位置插入内容、样式化选中的文本、样式化表单元素的占位符文本等,为页面提供更多的样式化和交互效果。
常用的伪类有以下几种:
这些伪类可以通过CSS的选择器来选择和样式化,它们可以用来根据元素的状态、位置、类型等进行选择和样式化,为页面提供更多的样式化和交互效果。
在JavaScript中,有以下几种数据类型:
基本数据类型(Primitive Data Types):
引用数据类型(Reference Data Types):
判断JavaScript数据类型的方法有多种:
使用typeof操作符:typeof操作符可以返回一个变量的数据类型,返回的结果是一个字符串。例如:typeof variable
。
使用instanceof操作符:instanceof操作符可以判断一个对象是否属于某个类或构造函数的实例。例如:variable instanceof Object
。
使用Object.prototype.toString方法:通过调用Object.prototype.toString方法,可以返回一个对象的具体类型。例如:Object.prototype.toString.call(variable)
。
使用typeof和null判断:由于typeof null返回"object",可以通过判断变量是否为null来判断是否为null类型。
使用Array.isArray方法:Array.isArray方法可以判断一个变量是否为数组类型。例如:Array.isArray(variable)
。
需要注意的是,typeof对于基本数据类型可以准确判断,但对于引用数据类型(除了函数)会返回"object",无法准确判断具体的引用数据类型。因此,结合多种方法可以更准确地判断JavaScript的数据类型。
ES6(ECMAScript 2015)是JavaScript的一个重要版本,引入了许多新的语法和功能。以下是ES6的一些主要特性:
块级作用域(Block Scope):引入了let和const关键字,可以在块级作用域中声明变量,解决了var关键字的变量提升和作用域问题。
箭头函数(Arrow Functions):使用箭头(=>)定义函数,简化了函数的写法,并且自动绑定了this。
模板字符串(Template Strings):使用反引号(`)包裹字符串,可以在字符串中插入变量和表达式,提供了更方便的字符串拼接方式。
解构赋值(Destructuring Assignment):可以从数组或对象中提取值,并赋给变量,简化了变量的声明和赋值过程。
默认参数(Default Parameters):在函数定义时可以为参数设置默认值,简化了函数调用时的参数传递。
扩展运算符(Spread Operator):使用三个点(…)可以将数组或对象展开,方便地进行数组合并、对象合并等操作。
类(Classes):引入了class关键字,可以使用面向对象的方式定义类和构造函数,并进行继承和方法的定义。
模块化(Modules):引入了import和export关键字,可以将代码分割成多个模块,方便地进行模块的导入和导出。
Promise:提供了一种更优雅的处理异步操作的方式,解决了回调地狱的问题。
箭头函数:使用箭头(=>)定义函数,简化了函数的写法,并且自动绑定了this。
迭代器和生成器(Iterators and Generators):引入了迭代器和生成器的概念,可以更方便地进行迭代操作。
模块化(Modules):引入了import和export关键字,可以将代码分割成多个模块,方便地进行模块的导入和导出。
这只是ES6的一部分特性,还有其他一些特性如Map、Set、Promise、Symbol等。ES6的引入大大提升了JavaScript的开发效率和代码质量,成为了现代前端开发的基础。
let
、const
和var
是JavaScript中用于声明变量的关键字,它们之间有以下区别:
作用域:let
和const
都是块级作用域,而var
是函数级作用域。块级作用域指的是在{}
内部声明的变量只在该块内部有效,而函数级作用域指的是在函数内部声明的变量在整个函数内部都有效。
变量提升:let
和const
不存在变量提升,即在声明之前使用会报错,而var
存在变量提升,即可以在声明之前使用变量。
重复声明:let
和const
不允许重复声明同一个变量,而var
允许重复声明同一个变量。
可变性:let
和var
声明的变量可以被重新赋值,而const
声明的变量是常量,不可被重新赋值。
全局对象属性:let
和const
声明的变量不会成为全局对象的属性,而var
声明的变量会成为全局对象的属性。
综上所述,推荐使用let
和const
来声明变量,因为它们具有更严格的作用域和更好的代码可读性,而var
在现代JavaScript中使用较少,主要是为了保持向后兼容性。
有多种方法可以对数组进行去重:
const arr = [1, 2, 2, 3, 3, 4, 5];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4, 5]
const arr = [1, 2, 2, 3, 3, 4, 5];
const uniqueArr = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(uniqueArr); // [1, 2, 3, 4, 5]
const arr = [1, 2, 2, 3, 3, 4, 5];
const uniqueArr = arr.reduce((result, item) => {
if (!result.includes(item)) {
result.push(item);
}
return result;
}, []);
console.log(uniqueArr); // [1, 2, 3, 4, 5]
const arr = [1, 2, 2, 3, 3, 4, 5];
const uniqueArr = Array.from(new Map(arr.map(item => [item, item])).values());
console.log(uniqueArr); // [1, 2, 3, 4, 5]
这些方法都可以实现数组去重,选择哪种方法取决于具体的需求和性能要求。
深拷贝和浅拷贝是在复制对象或数组时的两种不同方式:
浅拷贝:浅拷贝是指创建一个新的对象或数组,然后将原始对象或数组的引用复制给新对象或数组。这意味着新对象或数组与原始对象或数组共享相同的内存地址,当修改其中一个对象或数组时,另一个对象或数组也会受到影响。
深拷贝:深拷贝是指创建一个新的对象或数组,并递归地复制原始对象或数组的所有属性或元素。这意味着新对象或数组与原始对象或数组完全独立,修改其中一个对象或数组不会影响另一个对象或数组。
要实现一个深拷贝,可以使用递归和判断数据类型的方法来复制对象或数组的所有属性或元素。下面是一个简单的实现示例:
function deepClone(obj) {
// 判断是否为对象或数组
if (typeof obj !== 'object' || obj === null) {
return obj;
}
// 创建新的对象或数组
const clone = Array.isArray(obj) ? [] : {};
// 递归复制属性或元素
for (let key in obj) {
clone[key] = deepClone(obj[key]);
}
return clone;
}
使用示例:
const obj = {
name: 'John',
age: 30,
hobbies: ['reading', 'coding'],
address: {
city: 'New York',
country: 'USA'
}
};
const cloneObj = deepClone(obj);
console.log(cloneObj);
这样就可以实现一个简单的深拷贝函数。需要注意的是,该实现只适用于普通的对象和数组,对于包含函数、正则表达式等特殊类型的对象可能会出现问题。在实际开发中,可以使用第三方库如lodash的cloneDeep
方法来实现更完善的深拷贝功能。
Vue 的生命周期包括以下几个阶段:
beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。在这个阶段,实例的属性和方法还没有被初始化。
created:在实例创建完成后被调用。在这个阶段,实例的属性和方法已经被创建,可以访问和操作。
beforeMount:在挂载开始之前被调用。在这个阶段,模板编译已经完成,但是还没有将模板渲染到页面上。
mounted:在挂载完成后被调用。在这个阶段,实例已经被挂载到页面上,可以进行 DOM 操作。
beforeUpdate:在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。在这个阶段,可以对数据进行修改。
updated:在数据更新之后被调用,发生在虚拟 DOM 重新渲染和打补丁之后。在这个阶段,可以执行一些操作,比如访问更新后的 DOM。
beforeDestroy:在实例销毁之前被调用。在这个阶段,实例仍然完全可用,可以执行一些清理操作。
destroyed:在实例销毁之后被调用。在这个阶段,实例的所有事件监听器和子组件都被移除,可以进行一些最终的清理工作。
这些生命周期钩子函数可以用来在不同的阶段执行一些操作,比如初始化数据、发送网络请求、订阅事件、操作 DOM 等。通过在对应的生命周期函数中编写代码,可以实现更精细的控制和操作。
在 Vue 中,组件之间可以通过以下几种方式进行通讯:
Props 和事件:父组件可以通过 props 将数据传递给子组件,子组件可以通过 $emit 触发事件并将数据传递给父组件。
自定义事件:可以使用 $emit 和 $on 在组件之间传递消息和触发事件。
中央事件总线:可以创建一个全局的 Vue 实例作为事件总线,通过 $emit 和 $on 在任意组件之间传递消息和触发事件。
Vuex:Vuex 是 Vue 的官方状态管理库,可以用于管理应用的状态。通过在 Vuex 中定义状态和操作,不同组件可以通过读取和修改共享的状态来进行通讯。
$refs:可以使用 $refs 来访问子组件的属性和方法。
provide 和 inject:父组件可以通过 provide 提供数据,子组件可以通过 inject 注入数据。这种方式可以实现跨层级的组件通讯。
EventBus:可以使用一个独立的事件总线对象来进行组件之间的通讯。
$parent 和 $children:可以使用 $parent 和 $children 来访问父组件和子组件的属性和方法。
以上是常用的组件通讯方式,根据具体的场景和需求,选择合适的方式进行组件之间的通讯。