前端面试题(2)

1. Vue 是什么?
渐进式 JavaScript 框架。
2. 为什么要学习 Vue?
主流三大前端框架:Angular(谷歌)、react(Facebook)和 Vue
3. 预备知识:html 、css 、javascript
html: 标签,属性,页面结构与行业标准。
css: 样式规则,布局
javaScript: 对象,数组、表达式,函数,闭包。
// 监听属性,侦听器 和 表单元素搭配进行监听
watch: {
    // 监听回调函数的参数(当前的值/已更新的值, 第二个参数可选, 是原来的值)
    username: function (newVal, oldVal) {
        this.userList.forEach((value) => {
            if (newVal === value) {
                alter('该用户已经存在!')
                document.getElementByTagName('input').focus() // 使表单元素获取焦点
            }
        })
    }
}
// 第二种写法:
watch: {
    username: {
        handler (newVal, oldVal) {
            this.userList.forEach((value) => {
                if (newVal === value) {
                    alter('该用户已经存在!')
                    document.getElementByTagName('input').focus()// 使表单元素获取焦点
                }
            })
        }
    }
}
4. 计算属性 computed 和 计算方法属性 methods 之间的区别
相同: 计算属性和方法属性可以完成相同的功能
不同: 计算属性依赖缓存, 只有相关依赖数据发生变化才会重新计算, 性能更好。
	  方法属性动态性更强, 只要重新渲染, 方法总会被调用, 实时性更好。

5. v-ifv-show 之间的区别
v-if 控制模板元素的存在或移除, 移除是真正的删除了该元素(删除的是 DOM 元素)
v-show 控制模板元素的显示和隐藏, 隐藏仅仅是用 css 控制显示(dispaly: none)
// 1. Confirm('所要提示的消息内容')方法:信息提示是否删除窗。返回值为布尔值 true或者false。用于显示一个带有指定消息和确认及取消按钮的对话框。如果访问者点击"确定",此方法返回true,否则返回false。
// 2. prompt() 方法用于显示可提示用户进行输入的对话框。prompt(text,defaultText)第一个参数为提示信息,第二个参数为要修改的内容,可以为空 此时返回为空。这个方法最终返回的是字符串defaultText。
// 3. insertBefore() 方法可在已有的子节点前插入一个新的子节点。
// 4. Switch的用法:
switch(变量){
    case 变量值1:
        // 语句1;
        break;
    case 变量值2:
        // 语句2;
        break;
        ...
    default:
        //...;
        break;
}
 // 5. input::-webkit-input-placeholder{color:#a9a9a9;}
// 6. 父元素.appendChild(添加的元素):向父级元素末尾添加子元素。
// 1. 父组件传递数据给子组件
父组件中的数据传递给子组件通过 props 属性。props 是一个数组, 每个元素对应一个组件变量。在挂载点的组件模板上, 使用 v-bind 指令进行绑定。
例如:v-bind: 变量名 = '父组件中要绑定的数据变量名'
	// 父组件
	<Son :child="parent"></Son>
    data(){
        return {
			parent: '我是父组件中的数据'
        }
    }
	// 子组件
	props:['child']

// 2. 子组件传递数据给父组件
	// 子组件
	this.$emit('sendDataToParent', '我是子组件中的数据')
	// 父组件
	<Son @getDataChild="sendDataToParent"></Son>
    methods:{
        getDataChild(data){
            console.log(data) // 我是子组件中的数据
        }
    }
// 3. 同级组件之间相互传递数据(同级组件之间无法直接进行数据通信, 可以通过创建一个空 Vue 实例做中介)(01.总线方式) (02.vuex)
// 3.1 创建空的中间 Vue 实例
	import Vue from 'Vue'
	export default new Vue
// 3.2 组件1发送数据给中间商
	import Bus from '../bus/bus.js'
    methods: {
        send () {
            Bus.$emit('sendDataToMiddle', '组件1中的数据发送给中间组件')
        }
    }
// 3.3 组件2接受总线发送的数据
	import Bus from '../bus/bus.js'
    create() {
        Bus.$on('sendDataToMiddle', (data) => {
            console.log(data) // 组件1中的数据发送给中间组件
        })
    }

6. 插槽的用法 slot
插槽就是一个预留的占位符, 最终会被组件中的指定内容所替换。
// 01. v-cloak 用来防止 {{}} 表达式闪烁问题
 // 使用方法
 <style>
     [v-cloak]{
         display: none
     }
 </style>
<span v-cloak>{{ name }}</span>
//02. v-bind 可以给 html 元素或者组件动态地绑定一个或多个特性.例如动态绑定 style 和 class
// 03. 非常频繁地切换,使用 v-show。条件很少改变,使用 v-if 较好。
.stop -> 调用 event.stopPropagation()
.prevent -> 调用 event.prevenDefault()
.capture -> 添加事件侦听器绑定的元素本身触发时才触发回调
.self -> 只当事件是从侦听器绑定的元素本身触发时才触发回调
.{keyCode | keyAlias } -> 只当事件是从特定键触发时才触发回调
.native -> 监听组件根元素的原生事件
.one -> 只触发一次回调
.left 只当点击鼠标左键时触发
.right 只当点击鼠标右键时触发
.middle 只当点击鼠标中键时触发
.passive 以 {passive: true} 模式添加侦听器
7. v-pre 指令
v-pre 指令跳过这个元素和它的子元素的编译。
<span>{{this will not be compiled}}</span> // 输出结果为: {{this will not be compiled}}
<span v-pre>{{msg}}</span>    即使data里面定义了msg这里仍然是显示的{{msg}}
8 v-text指令
v-text指令和{{}}一样,唯一的区别是: {{}}会造成闪烁问题(网上慢)。v-text 不会有闪烁问题。
如果还想用 {{}}又不想有闪烁问题,则使用 v-cloak 来处理。
9. 指令
v-html
v-show 条件显示和隐藏(dispaly: none)
v-if 真正的条件渲染(操作 DOM 创建与销毁)
v-else
v-else-if
v-for
v-on
v-bind
v-model
v-pre
10. 计算属性computed和方法methods的区别
(1) 使用方法可以把复杂逻辑封装起来, 每使用一次就调用一次, 重复使用效率不高。
(2) 计算属性不要让模板逻辑太重, 解决性能问题。
(3) 计算属性当属性来使用,方法当方法来调用
(4) 计算属性会缓存计算的结果, 多次使用也只调用一次
(5)计算属性不能当作方法使用,所有不能用于事件处理函数,事件处理函数还是使用 methods方法
 // 计算属性相比方法的优势就在于会缓存计算的结果。效率很高
computed:{
	事件名:{
	// 当你访问事件会自动执行get中的代码。
        get(){
            要执行的代码段。
        },
        //当你给实例,事件名=xxx (赋值)时,则会执行set()方法。
        set(){
        }
	}
}

11. localStorage 本地存储
localStorage:本地存储;H5新增的本地存储,有两个最重要的API。是一个对象,提供两个方法:
(1)localStorage.getItem用来获取值
	// localStorage.setItem(键名) 取的是字符串的形式,需要转化一下,通过JSON.parse()
(2)localStorage.setItem用来修改值(赋值)
	// localStorage.getItem(键名,存储内容) 存储的内容一定要是字符串的形式,可以通过JSON.stringify()进行转化,即对象转成字符串。
(3)localStorage.removeItem用来删除值

// JSON.stringify(): 对象转成字符串
// JSON.parse(): 把字符串转化对象。

12. watch监听
watch 监听数据变化
监听数据或者对象需配置深度监听watch: deep:true
watch: {
    监听对象: {
        handler(newVal, oldVal){
            // 监听对象改变时,要执行的代码
        },
        deep: true // 深度监听
       immediate: true // 立即执行
    }
}
// 注册 hash 的改变事件
window.onhashchange = function () {
    console.log(window.location.hash.substr(1))
}

// string.substr(start, length) start 起始位置, length 截取的长度(若不设置,表示截取到最后)
string.substr(): 将在字符串 string 中抽取并返回一个子字符串,原字符串不变。

// location.hash:获取网页的哈希值
13. 自定义指令
// 全局语法: Vue.directive('指令名称', { 选项参数 })
Vue.directive('指令名称', {
    bind: (el, binding) => {
        // 得不到父元素
    },
    inserted: (el, binding) => {
        // 可以得到父元素
    },
    update: (el, binding) =>{
        // 模板更新前的内容
    },
    componentUpdated: (el, binding) => {
        // 模板更新后的内容
    },
    unbind: (el, binding) => {
        // 卸载一下,定时器
    }
})
// bind 和 inserted的相同之处:上来都会执行一次,以后再也不会执行。不同之处:bind获取不到父元素,inserted可以获取父元素节点。
// 局部注册语法:directives: { '指令名': { 选项参数 }}
directives: {
    focus: {
        inserted: (el, binding) => {
            el.focus()
        }
    }
}
// 使用
// 当页面加载时, 该元素将获取焦点
<input v-focus>

// 注意事项
// 在模板中使用自定义指令必须加上 v- 前缀
// 对于驼峰命名的自定义指令, 在使用的时候使用 - 连接即可
// 全局注册的自定义指令可以在任何组件中使用
// 组件内注册的自定义指令只能在被该组件管理的模块中使用
    
// 自定义自动获取输入框 input 焦点
<input v-focus/>
// 注册一个全局自定义指令 'v-focus'
Vue.directive('focus', {
	// 当被绑定的元素插入到 DOM 中时.....
    // el 参数就是你作用该指令的 DOM 元素
    inserted: (el) => {
        // 聚焦元素
        el.focus()
    }
})
// array.includes():判断数组 array 中是否含有指定的元素,若存在,返回 true, 反之返回false
14. 全局组件和局部组件
组件的定义方式分为两种, 全局组件和局部组件
全局组件定义在全局,在任意组件中都可以直接使用。
局部组件定义在组件内部, 只能在当前组件使用。
// 建议把通用的组件定义在全局, 把不通用的组件定义在局部。
1. 单文件组件由三个部分组成:
	1. tempalte (html部分、结构)只能存在一个更元素
	2. script (javascript部分、行为)
	3. style (css部分、样式) scoped样式只在当前组件内生效
2. 子父组件之间的交互(数据传递)-> 子 props提供一个带有验证需求的对象, 而不是一个字符串数组。props的验证
	数据传递类型限制(验证)
	(1) 数据类型验证(string, number....)
	(2) 多数据类型验证(是个数组,例如: [String, Number])
	(3) 必选项(required)
	(4) 默认值(default)
	(5) 对象, 数组类型的默认值(default 是个函数)-> 父 $emit
    	子组件中需要通过 this.$emit('事件名', 要发送的数据) 发送数据。
        父组件中需要在子组件标签中绑定事件 @
 3. 插槽slot (插槽就是一个预留的占位符, 最终会被组件中的指定内容所替换)
 	单个插槽<slot></slot>
	具名插槽 <slot name="s1"></slot> 在标签中引用 slot="s1"
	作用域插槽 数据是子传父。父组件中用 slot-scoped = "接收数据"; 子组件通过 v-bind 绑定属性发送数据。
 4. 动态组件
 	<component :is=""></component>
	kenp-alive: 组件缓存
 // 请求的数据、操作DOM 一般放在生命周期函数 mounted 中
 5. vue.js 是一套构建用户界面(UI)的渐进式 javascript 框架
 6. MVVM 的介绍
 	MVC:
		M: model数据模型(专门用来操作数据的)
		V: View 视图(对于前端就是页面)
		C: Controller 控制器(视图和数据模型沟通的桥梁, 用于处理业务逻辑)
	MVVC:
		M: model数据模型
         V: view视图
         VM: ViewModel 视图模型
7. insertBefore() 方法可在已有的子节点前插入一个新的子节点
15. scss 的使用
npm install stylus -save
npm install stylus-loader -save
16. 技术
vue
vue-router
vuex 
mint-ui, element-ui
vue-lazyload // 懒加载库
vue-scroller、 better-scroll、swiper // 滑动库
moment、date-fns // 日期处理库

17. 项目结构分析
build: webpack 相关的配置文件夹(基本上不需要修改)
config: webpack 相关的配置文件夹(基本上不需要修改)
	index.js: 指定的后台服务的端口号和静态资源文件夹
node_modules
src: 源码文件夹
	main.js: 应用入口js
static: 静态资源文件夹
.babelrc: babel的配置文件
.editorconfig: 通用编辑器的编码/格式进行一定的配置
.eslintignore: eslint 检查忽略的配置
.eslintrc.js: eslint 检查的配置
index.html: 主页面文件
package.json: 应用包配置文件
README.md: 应用描述说明的 readme 文件
18. 项目源码目录设计
src
	api: 与后台交互模块文件夹
	common: 通用资源文件夹, 如: fonts/img/stylus
	components: 非路由组件文件夹
	filters: 自定义过滤器模块文件夹
	mock: 模拟数据接口文件夹
	pages:路由组件文件夹
	router: 路由器文件夹
	store: vuex 相关模块文件夹
	app.vue: 应用组件
	main.js: 入口文件
19. 安装 stylus 依赖包
// 1. 安装
npm install stylus stylus-loader --save-dev

// 2. 应用
<style lang="stylus" scoped></style>
20. 移动端
// 1. 适配 viewport
<meta name="viewport" content="
	width = "device-width",
    initial-scale = 1.0,
    maximum-scale = 1.0,
    minimum-scale = 1.0,
    user-scalable = no
">

// 2. 解决点击响应延时 0.2s 问题 (安装 fastclick依赖包)
<script
	src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js">
</script>
<script>
        if ('addEventListener' in document){
            document.addEventListener('DOMContentLoaded', function(){
                FastClick.attach(document.body)
            }, false)
        }   
</script>
21. 引用 vue-router
// 1. 安装
npm install vue-router --save-dev
22. 箭头函数
	箭头函数中 this 指向 父级作用域的 this。 是通过查找作用域链确定 this 的值,也就是说,看的是上下文的 this, 指向的是定义它的对象,而不是使用时所在的对象。
	普通函数中 this 指向的是 它的直接调用者,.
23. 闭包
	闭包是一个函数,两个函数彼此嵌套, 内部函数就是闭包。
	闭包形成的条件:内部函数需要通过 return 给返回出来

eg: function func () {
    return function func () {
        
    }
}
24. 预编译
	预编译: 其实就是当你写一段代码, 系统会在代码执行的前一刻自动扫描一遍你的代码, 检查代码是否出现了低级的语法错误, 找到你所定义的全局变量以及函数。
25. 缓存
	HTTP Cache 是我们开发中接触最多的缓存, 它分为强缓存和协商缓存
	强缓存: 直接从本地副本比对读取, 不去请求服务器, 返回的状态码 200
	协商缓存: 会去服务器比对, 若没有改变才直接读取本地缓存, 返回的状态码 304
26. 节流
	// 所谓节流, 就是连续触发事件, 但是在 n 秒内只执行一次函数。节流会稀释函数的执行频率
function debounce (func, wait) {
    let timeout
    return function () {
        let context = this
        let args = arguments
        if (timeout) {
            clearTimeout(timeout)
        }
        timeout = setTimeout(() => {
            func.apply(context, args)
        }, wait)
    }
}
27. 防抖
// 所谓防抖, 就是指触发事件后在 n 秒内函数只能执行一次, 如果在 n 秒内又触发了事件, 则会重新计算函数执行时间。
function throttle (func, wait) {
    let timeout
    return function () {
        let context = this
        let args = arguments
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null
                func.apply(context, args)
            }, wait)
        }
    }
}
28. 原型链
	原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链, 原型对象也是普通的对象, 是对象一个自带隐式的 __proto__ 属性。
29. 单页面
// 优点
1. 用户体验好、快、内容改变不需要重新加载整个页面, 基于这个点对服务器压力较小。
2. 前后端分离
3. 页面效果会比较炫酷

// 缺点
1. 不利于 seo
2. 导航不可用, 如果一定要导航需要自行实现前进、后退
3. 初次加载时耗时多
4. 页面复杂度提高很多
20. 对象创建方式
20.1 工厂模式
	工厂模式: 在一个函数中创建好对象, 然后把对象返回
	
eg: function createPerson (name, age, job) {
    let obj = new Object()
    obj.name = name
    obj.age = age
    obj.job = job
    obj.sayName = function () {
        console.log('this.name')
    }
    return obj
}

let person1 = createPerson('Nicholas', 29, 'software Engineer')
20.2 构造函数模式
function Person (name, age, job) {
 	this.name = name
    this.age = age
    this.job = job
    this.sayName = function () {
        console.log(this.name)
    }
}

let person1 = new Person('Nicholas', 29, 'software Engineer')
20.3 原型模式
// 第一种写法
function Person () {
    
}
Person.prototype.name = "Nicholas"
Person.prototype.age = 29
Person.prototype.job = "software Engineer"
Person.prototype.sayName = function () {
    console.log(this.name)
}
// 第二种写法
function () {
    
}
Person.prototype = {
    name: 'Nicholas',
    age: 29,
    job: 'software Engineer'
    sayName: function () {
    	console.log(this.name)
	}
}
常用: 用一个包含所有属性和方法的对象字面量来重写整个原型对象, 并设置 constructor 属性
20.4 组合使用构造函数和原型
// 组合使用构造函数模式和原型模式:构造函数模式用于定义实例属性, 原型模式用于定义方法和共享属性

function Person(name, age, job) {
    this.name = name
    this.age = age
    this.job = job
}
Person.prototype.sayName = function () {
    console.log(this.name)
}
21. Javascript 继承
21.1 原型链式继承
function SuperClass () {
    this.books = ['css', 'js', 'html']
}

function SubClass () {
    
}

SubClass.prototype = new SuperClass()
var obj1 = new SubClass()
var obj2 = new SubClass()

console.log(obj2.books) // ['css', 'js', 'html']

obj1.books.push('设计模式')

console.log(obj2.books) // ['css', 'js', 'html', '设计模式']

// 原型链式继承的缺点:
	(1) 由于子类通过其原型 prototype 对父类实例化, 继承了父类。如果父类中的共有属性要是引用类型, 就会在子类中被所有实例共用, 因此子类的实例更改由父类构造函数中继承来的共有属性就会直接影响到其他子类。
	(2) 子类实现的继承是靠其原型 prototype 对父类的实例化实现的, 因此咋创建父类的时候, 是无法向父类传递参数的, 因而在实例化父类的时候也无法对父类构造函数内的属性进行初始化。
21.2 构造函数继承
function SuperClass (price) {
    this.books = ['css', 'js', 'html']
    this.price = price
}
SuperClass.prototype.sayBooks = function() {
    console.log(this.price)
}

function SubClass (price) {
    // 此句是构造函数的重点, 或者可以 SuperClass.apple(this, [price])
    SuperClass.call(this, price)
}

var obj1 = new SubClass(50)
var obj2 = new SubClass(60)
console.log(obj2.books) // ['css', 'js', 'html']
obj1.books.push('设计模式') // ['css', 'js', 'html', '设计模式']
console.log(obj2.books) // ['css', 'js', 'html']

obj2.sayBooks() // TypeError

// 由于 call 或者 apply  方法可以改变函数 this 的指向, 因此在子类中, 对 superClass 调用这个方法就是将子类中的变量在父类中执行一遍, 由于父类是给 this 绑定属性的, 因此子类自然就继承了父类的共有属性.
// 由于这个类继承没有涉及原型 prototype, 这样父类的原型方法自然不会被子类继承, 如果想要被继承, 就必须要放在构造函数中, 这样创建出来的每一个实例都会单独拥有一份而不能被公用, 违背了代码复制的原则。
21.3 类式继承和构造函数继承结合
function SuperClass (price) {
    this.books = ['css', 'js', 'html']
    this.price = price
}
SuperClass.prototype.sayBooks = function () {
    console.log(this.price)
}

function SubClass(price){
    // 此句是构造函数的重点, 或者可以SuperClass.apple(this.[price])
    SuperClass.call(this, price)
}

// 原型继承
SubClass.prototype = new SuperClass()
var obj1 = new SubClass(50)
var obj2 = new SubClass(60)
console.log(obj2.books) // ['css', 'js', 'html']
obj1.books.push('设计模式') // ['css', 'js', 'html', '设计模式']
console.log(obj2.books) // ['css', 'js', 'html']

obj2.sayBooks() // TypeError
22. 同源策略
	同协议同域名同端口, 是一个安全策略。
	同协议: http 或者 https
	同域名: www.baidu.com
	同端口:8080
    同源策略是浏览器的一个安全功能, 不同源的客户端脚本在没有明确授权的请求下, 不能读写对方资源。(也就是跨域)
    
23. 解决跨域问题
	(1) 降域:用 document.domain, 此方式的特点:只能在父域名和子域名之间使用, 存在安全性问题, 当一个站点被攻击后, 另一个站点会引起安全漏洞。这种方法只适用于 Cookie 和 iframe 窗口。
	(2) JSONP跨域, 基本原理是:通过动态的创建 script 标签, 然后利用 src 属性进行跨域。
	存在问题:使用这种方法, 只要是个网站都可以拿到 b.com 里的数据.
	存在安全性问题; 只能是 GET, 不能是 POST; 可以被注入恶意代码, 篡改页面内容, 可以采用字符串过滤来规避此问题。
	(3) CORS 是一个 W3C 标准, 全称是 "跨域资源共享"(Cross-origin resource sharing).
大致流程: 浏览器向服务器发送 XMLHTTPRequest 请求, 添加响应头声明 Access-Control-Allow-Origin
	(4) CORS 和 JSONP, 或者后端设置代理。
	
24. Cookie 的弊端
IE6 或者更低版本最多 20 个 cookie
IE7 和之后的版本最多可以有 50个cookie
Firefox 最多 50个cookie
chrome 和 Safari 没有强硬限制
25. positionabsolutefixed 共同点与不同点?
1) 共同点
	1. 改变行内元素的呈现方式, display 被设置为 block
	2. 让元素脱离普通文档流, 不占据空间
	3. 默认会覆盖到非定位元素上
2) 不同点
	absolute 的根元素是可以设置的, 而 fixed 的根元素固定为浏览器窗口
	当你滚动网页, fixed 元素与浏览器窗口之间距离不变的
26. JSON
JSON 是一种轻量级的数据交换格式, 它是基于 JavaScript 的一个子集。数据格式简单, 易于读写, 占用带宽小。
JSON.stringify()
JSON.parse()
27. call()apply() 的区别和作用
作用: 动态改变某个类的方法的运行环境。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值