一:防抖节流
防抖:一个频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。
例:防抖经常用在我们搜索框输入搜索,点击提交,防止等;
节流:一个频繁触发的函数,在规定时间内,函数执行一次后,只有大于设定的执行周期后才会执行第二次。
例:节流一般在onresize、mousemove、滚动事件等事件中使用,防止过多的请求造成服务器压力
二:Css盒模型
盒模型的组成:元素的内容content、元素的内边距padding、元素的外边距margin、元素的边框border
盒模型分为 : W3C标准盒子 、IE盒子
W3C标准盒子(content-box):又称内容盒子,是指块元素box-sizing属性为content-box的盒模型,盒子总宽度 = margin + border + padding + width
IE盒子(border-box):又称怪异盒模型(边框盒子),是指块元素box-sizing属性为border-box的盒模型,盒子总宽 = margin + width
三:数组都有哪些方法
1.toString()与join()一样都是把数组转成以逗号分割的字符串
2.pop() 删除数组的最后一项
3.push() 往数组最后添加新数据
4.shift() 删除数组最前面的一项
- unshift() 往数组开头添加新数据
- splice() 方法可用于向数组添加新项或者删除数组
7.concat()连接两个数组生成一个新数组
8.slice()
//slice 与 splice 的区别
var arr=['a','b','c','d','e','f'];
arr.splice(1,3); // arr = ['a', 'e', 'f']; arr.splice(1,3)=['b', 'c', 'd'];
var arr=['a','b','c','d','e','f'];
arr.slice(1,3); // arr = ['a','b','c','d','e','f']; arr.slice(1,3)=['b', 'c']
四:var、const、let的区别
var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
const定义的变量不可以修改,而且必须初始化
let是块级作用域,函数内部使用let定义后,对函数外部无影响。
五:vue生命周期
beforeCreate( 创建前 )
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data, computed等上的方法和数据。
created ( 创建后 )
实例已经创建完成之后被调用,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,el没有。 然而,挂在阶段还没有开始, $el属性目前不可见,这是一个常用的生命周期,因为你可以调用methods中的方法,改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上,,获取computed中的计算属性等等,通常我们可以在这里对实例进行预处理,在这里发ajax请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子beforeRouteEnter中完成
beforeMount
挂在开始之前被调用,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。
mounted
挂在完成,也就是模板中的HTML渲染到HTML页面中,此时一般可以做一些ajax操作,mounted只会执行一次。
beforeUpdate(更新前)
在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程
updated(更新后)
在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用
beforeDestroy(销毁前)
在实例销毁之前调用,实例仍然完全可用,这一步还可以用this来获取实例,一般在这一步做一些重置的操作,比如清除掉组件中的定时器和监听的dom事件
destroyed(销毁后)
在实例销毁之后调用,调用后,所有的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用
六:vue react区别
相同点
1.都支持服务器端渲染
2.都有虚拟dom,组件化开发,都有‘props’的概念,允许父组件往子组件传送数据,都实现webComponent规范
3.数据驱动视图
4.都有支持native的方案,React的React native,Vue的weex
5.构建工具
React和Vue都有自己的构建工具,你可以使用它快速搭建开发环境。React可以使用Create React App (CRA),而Vue对应的则是vue-cli。都有管理状态,React有redux,Vue有自己的Vuex
区别
设计思想
react
1.函数式思想,all in js ,jsx语法,js操控css
2.单项数据流
3.setState重新渲染
4.每当应用的状态被改变时,全部子组件都会重新渲染。当然,这可以通过shouldComponentUpdate这个生命周期方法来进行控制,如果为true继续渲染、false不渲染,但Vue将此视为默认的优化。
vue
1.响应式思想,也就是基于数据可变的。把html、js、css、组合到一起,也可以通过标签引擎组合到一个页面中
2.双向绑定,每一个属性都需要建立watch监听(页面不用,涉及到组件更新的话需要)
3.Vue宣称可以更快地计算出虚拟 DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树
性能
react ----大型项目、优化需要手动去做,状态可控
vue ------中小型项目、状态改变需要watch监听,数据量太大的话会卡顿
扩展性
react
1 类式写法api少,更容易结合ts
2 可以通过高阶组件来扩展
vue
1 声明式写法,结合ts比较复杂
2 需要通过mixin方式来扩展
七:vue路由守卫
vue-router提供了导航钩子:全局前置导航钩子 beforeEach和全局后置导航钩子 afterEach
导航钩子3个参数(to,from,next):
- to:将要进入的路由对象
- from:将要离开的路由对象
- next:调用该方法后,才能进入下一个钩子函数(afterEach不接收next只有to/from)next函数,决定是否展示你要看到的路由页面
router.beforeEach(to,from,next){};
router.afterEach(to,from){}
组件内的守卫
到达这个组件时:
beforeRouteEnter:(to,from,next)=>{
console.log(this.数据)//undefined
//因为生命周期原因现在data数据还未渲染,所以要用
next(vm=>{
consoel.log(this.数据)//这里就可以得到data里的数据
})
}
离开这个组件时:beforeRouteLeave:(to,from,next)=>{}
确认离开next();取消离开next(false);
路由独享的守卫
beforeEnter:(to,from,next)=>{},用法与全局守卫一致。只是,将其写进其中一个路由对象中,只在这个路由下起作用。
八:vue的组件传值
父子组件传值
父传子
// 父组件
<user-detail :myName="name" />
//子组件
<script>
export default{
props:['myName'],
data() {
return {
name : this.myName // 把传过来的值赋值给新的变量
}
},
watch: {//侦听器
myName(newVal) {
this.name = newVal //对父组件传过来的值进行监听,如果改变也对子组件内部的值进行改变
//引用类型的值,当在子组件中修改后,父组件的也会修改,因其数据是公用的,其他同样引用了该值的子组件也会跟着被修改。可以理解成父组件传递给子组件的值,就相当于复制了一个副本,这个副本的指针还是指向父组件中的那个,即共享同一个引用。所以除非有特殊需要,否则不要轻易修改
}
},
methods: {
changeName() {
this.name = 'Lily' // 这里修改的只是自己内部的值,就不会报错了
},
}
}
</script>
子传父
方法一:
子组件绑定一个事件,通过 this.$emit() 来触发
在子组件中绑定一个事件,并给这个事件定义一个函数
// 子组件
<button @click="changeParentName">点击改变父组件的name</button>
<script>
export default {
methods: {
//子组件的事件
changeParentName: function() {
this.$emit('handleChange', 'aaa') // 触发父组件中handleChange事件并传参aaa
// 注:此处事件名称与父组件中绑定的事件名称要一致
}
}
}
</script>
在父组件中定义并绑定 handleChange 事件
// 父组件
<child @handleChange="changeName"></child>
methods: {
changeName(name) { // name形参是子组件中传入的值Jack
this.name = name
}
}
方法二:
通过 callback 函数
先在父组件中定义一个callback函数,并把 callback 函数传过去
// 父组件
<child :callback="callback"></child>
methods: {
callback: function(name) {
this.name = name
}
}
在子组件中接收,并执行 callback 函数
// 子组件
<button @click="callback('aaa')">点击改变父组件的name</button>
props: {
callback: Function,
}
方法三:
通过$parent /$children 或 $refs
访问组件实例
这两种都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。
这种方式的组件通信不能跨级
// 子组件
<script>
export default {
data () {
return {
title: '子组件'
}
},
methods: {
sayHello () {
console.log('Hello');
}
}
}
</script>
// 父组件
<template>
<child ref="childRef" />
</template>
<script>
export default {
created () {
// 通过 $ref 来访问子组件
console.log(this.$refs.childRef.title); // 子组件
this.$refs.childRef.sayHello(); // Hello
// 通过 $children 来调用子组件的方法
this.$children.sayHello(); // Hello
}
}
</script>
方法四:
$attrs和$listeners
//父组件
<template>
<child :name="name" :age="age" :infoObj="infoObj" @updateInfo="updateInfo" @delInfo="delInfo" />
</template>
<script>
import Child from '../components/child.vue'
export default {
name: 'father',
components: { Child },
data () {
return {
name: 'Lily',
age: 22,
infoObj: {
from: '上海',
job: 'policeman',
hobby: ['reading', 'writing', 'skating']
}
}
},
methods: {
updateInfo() {
console.log('update info');
},
delInfo() {
console.log('delete info');
}
}
}
</script>
//子组件
<template>
<grand-son :height="height" :weight="weight" @addInfo="addInfo" v-bind="$attrs" v-on="$listeners" />
// 通过 $listeners 将父作用域中的事件,传入 grandSon 组件,使其可以获取到 father 中的事件
</template>
<script>
import GrandSon from '../components/grandSon.vue'
export default {
name: 'child',
components: { GrandSon },
props: ['name'],
data() {
return {
height: '180cm',
weight: '70kg'
};
},
created() {
console.log(this.$attrs);
// 结果:age, infoObj, 因为父组件共传来name, age, infoObj三个值,由于name被 props接收了,所以只有age, infoObj属性
console.log(this.$listeners); // updateInfo: f, delInfo: f
},
methods: {
addInfo () {
console.log('add info')
}
}
}
</script>
//爷组件
<template>
<div>
{{ $attrs }} --- {{ $listeners }}
<div>
</template>
<script>
export default {
... ...
props: ['weight'],
created() {
console.log(this.$attrs); // age, infoObj, height
console.log(this.$listeners) // updateInfo: f, delInfo: f, addInfo: f
this.$emit('updateInfo') // 可以触发 father 组件中的updateInfo函数
}
}
</script>