v-model
v-model是一种语法糖,主要职责就是监听用户的输入以及更新数据。
v-model作用于不同的表单控件时绑定的属性不同,作用于text或textarea时绑定的是value属性和input事件;
作用于checkbox或radio时绑定的是checked属性和change事件
作用于select时绑定的是value属性和change事件。
vue2.0双向数据绑定缺陷
vue2采用发布-订阅方式,通过Object.defineProperty拦截属性的get/set。vue实例创建后无法检测到属性的新增或删除,只能追踪到数据的修改。
理由:vue实例创建后会遍历对象的所有属性并为每个属性添加get/set。get/set允许vue观察到数据的变化并触发更新。但是你在vue实例化后添加或删除一个属性不会被vue处理。
解决方案:通过Vue.set(obj,property, value)
不同检测到数组的变化。
vue在实现数组的响应式时使用了hack,把无法监听数组的情况通过重写数组的push/pop/shift/unshift/splice/sort/reverse方法来实现响应式。其他方法不行
Vue3.0 实现数据双向绑定
vue3通过Proxy实现双向数据绑定。proxy可以理解成在目标对象之前架设一层拦截,外界对该对象的访问必须先通过这层拦截,也就可以对外界的访问进行过滤和拦截。可以做一些日记记录,属性值验证。
vuex
vuex是一种状态管理工具,将全局组件的共享状态抽取出来为一个store,以一个单例模式存在,应用在任何组件中都可以使用。通过mutation修改state,mutation需要commit触发,action实际是触发mutation,mutation处理同步任务,action处理异步任务。
vuex的属性
state 是存储的单一状态;
getter 是state的计算属性;
mutations 是提交更改数据;
actions 提交mutation;
module 分割模块;
vuex实现原理
修改ElementUI的样式
1. 新建全局样式表,新建文件global.css,在main.js中引入,一般放在src/assets的style下。
2. 在vue页面下增加style标签。style标签不能使用scope属性。
3. 使用:deep(.className)
4. 通过内联样式修改。
ElementUI作用
vue2实现的组件库。提供了配套设计资源,帮助网站快速成型
导航守卫
通过跳转或取消的方式守卫导航。
全局前置守卫:router.beforeEach((to,from,next)=>{}),to表示即将进入的路由对象。from表示即将离开的路由对象。next进入下一个守卫。
next(false)中断当前导航。next("/")跳转到其他地址。当前导航被中断,然后进行一个新的导航。
全局后置钩子:router.afterEach((to,from)=>{})
路由独享守卫:beforeEnter:(to,from,next) =>{}
vue-router实现的懒加载
懒加载:打包构建时,js包会变得非常大。影响页面加载,需要把不同的路由对应的组件分割在不同的代码块。
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
js是如何监听HistoryRouter变化
1. 通过hash改变,利用window.onhashchange监听。
2.
HashRouter 和 HistoryRouter的区别和原理
vue-router默认 hash 模式,还有一种是history模式。
hash路由:
hash模式的工作原理是hashchange事件。可以在window监听hash变化。我们在url后添加#xx就可以触发这个事件。当url改变时,页面不会重新加载,也就是单页应用了。当hash变化时,不会向服务器发送请求,页面不会刷新,并且会触发hashchange事件。
hash模式会创建hashHistory对象。
history路由:
有html5的pushState和replaceState结合window.popstate事件来实现。可以改变url且不会发送请求。
区别:
history模式更加优雅。
pushState的url可以与当前url相同,也会触发添加记录到栈。hash设置的新值必须不同才会添加记录到栈。
pushState通过stateObject可以添加任意类型的数据
vue-router原理,哪个模式不会请求服务器
hash模式不会请求服务器,hash模式是在url后添加#号,通过hashchange事件监听url变化。hash虽然出现在url中,但不会被包括在请求中,对后端没影响。
H5的history模式,以"/"分割,需要服务器支持,将所有请求指向同一个html文件。
组件通信方式
1. props 和 $emit 父组件通过props传递数据给子组件;子组件通过$emit 传递数据给父组件。
2. provide 和 inject ,父组件通过provider来提供变量,子组件通过inject注入变量。
3. 中央事件总线。
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
emitter.emit("why", {name: "why", age: 18});
emitter.on("why", (info) => {
console.log("why:", info);
});
4. vuex或者pinia
vue生命周期中异步加载是在mounted还是created
一般在created里面;在mounted里面发请求会进行二次渲染,在created里面发请求会在后端响应后进行渲染。
vue生命周期函数
开始创建、初始化数据、编译模板、挂载dom、渲染->更新->渲染、销毁
1. 实例化组件实例:new Vue()
2. 初始化事件和生命周期:init events 和init lifecycle
3. beforeCreate函数:实例创建了,但是data的属性还么有绑定
4. 挂载数据:绑定data的属性
5. created函数:vue对象的属性有了,但是dom还没有生成,$el属性不存在。这里可以请求后端数据,更改数据不会触发updated函数。
6. beforeMount函数:此时数据还没有挂载到页面上,也就是{{}}中的变量还没有被数据替换。
7. 模板编译:用数据替换变量。
8. mounted函数:此时数据已经挂载到页面。
9. beforeUpdate函数:数据更新后,组件更新前执行,此数据一定是模板上出现的数据。
10. updated函数:组件更新后执行。
11. activated函数:keep-alive 组件激活时调用。
12. inactivated函数: keep-alive 组件停用时调用。
13. beforeDestroy函数:vue对象销毁之前调用。
14. destroyed:vue组件销毁后调用。
keep-alive
可以实现组件缓存。它是vue的一个内置组件。
1. 它能把不活动的组件实例保存在内存中。而不是直接销毁。
2. 它是一个抽象组件,不会被渲染到真实dom
3. include/exclude有条件的缓存。
4. activated/deactivated
5. 基于LRU(Least Recently Used)算法,将需要缓存的VNode节点保存在this.cache中/在render时,如果VNode的name符合在缓存条件(可以用include以及exclude控制),则会从this.cache中取出之前缓存的VNode实例进行渲染。
为什么vue的data是函数
js中只有函数构成作用域,对象和if都不构成,data是函数时每个组件实例有自己的作用域,每个实例相互独立,互不影响。
vue中$nextTick作用
为了获取更新后的dom。
vue的dom更新是异步的。即修改数据不会立马更新视图,而是监听数据,并缓存在同一事件循环中,等同一事件循环中所有数据变化后,统一更新视图。
nextTick主要使用了宏任务和微任务。根据执行环境分别采用Promise,MutationObserver,setImmediate。
v-if和v-show区别
v-if和v-show都是用来隐藏元素,v-if可以和v-else配合使用,v-if更消耗性能,因为v-if在隐藏显示过程中有dom的添加和删除。v-show只操作css。
v-show不论真假,第一次渲染的时候都会编译出来,也就是添加到dom,之后根据真假设置display:none来隐藏。
v-if在首次渲染时如果条件假,什么操作也不做。当条件为真时才会编译,添加到dom。当条件为假时会删除元素。
vue的列表为什么要加key
key可以标识组件的唯一性,可以更高效的更新虚拟dom。
vue和react的diff算法大致相同。
首先对比操作前后的dom树的同层节点。
当某一层有很多节点时,如果插入一个节点。diff在没有key的情况下将原来的节点更新为新的节点。而在有key的情况下就可以直接做插入。
jquery和vue比较
jquery是轻量级js库;
vue是前端js库,专注于mvvm模式的vm层,通过双向数据绑定把view和model连接起来。通过对数据的操作完成对页面的渲染。
vue特点:操作简单,模块化,单页面,组件复用,虚拟dom。
为什么选择vue做页面
1. vue使用了mvvm框架,通过声明式渲染和响应式数据绑定避免dom操作。
2. 单页面应用,配合vue-router可以开发复杂的单页应用。
3. 轻量化,易学习。
4. 渐进式,兼容性。vue只关注视图层,易于上手,而且便于于第三方库整合。
5. 视图组件化。通过组件拼装一个页面。每个组件可复用,组件内可以有自己的数据,逻辑和代码。
6. 虚拟dom。完全避免dom操作。
7. 社区支持。
双向数据绑定原理
mvc实现了单向数据绑定,而双向数据绑定就是在单项绑定的基础上添加了change事件。来动态修改model和view。
实现方式:
8. 发布-订阅模式:一般通过sub和pub的方式实现视图和数据的监听。更新数据通过$set。
9. 数据劫持:vuejs采用数据劫持结合发布-订阅。通过Object.defineProperty劫持get/set,在数据变动时发布消息给订阅者。触发监听回调。
new Vue原理
1. new Vue 会调用Vue原型链上的init方法进行初始化。
2. 首先是initLifecyle初始化生命周期。
3. initEvents 初始化当前实例的自定义事件。
4. initRenders 解析slots
5. 触发生命周期钩子beforeCreate。
6. initInjections。在初始化data和props之前完成依赖注入。
7. initState,完成data和props初始化。
8. initProvide,对依赖注入进行解析。
9. 完成对数据的初始化,触发生命周期钩子created。
10. 进入挂载,将vue语法通过vue-loader解析成虚拟dom树,虚拟dom树与数据完成双向数据绑定,触发钩子beforeMount。
11. 将解析好的虚拟dom树通过vue渲染成真实dom。触发钩子mounted。
vue首屏白屏如何解决
1. 路由懒加载
2. vue-cli开启打包压缩。
3. cdn加速
4. 开启vue服务渲染。
5. 用webpack的extenals属性分离库文件。
6. 删除不必要的console
单页和多页应用的区别
单页应用:一开始加载所有必须的html、css、js文件。在交互时由路由动态引入,单页面的跳转,仅刷新局部资源。
多页应用:一个应用中有多个页面。页面跳转是整页刷新。
单页优点:用户体验好、内容改变不需要加载整个页面;前后端分离;
单页缺点:不利于seo、首页加载慢、页面复杂度高。
路由跳转和location.href区别
location.href跳转,会刷新页面。
路由跳转无刷新页面。
delete和vue.delete区别
delete会删除数组的值,但位置不会删除。
vue.delete会删除位置。
let arr1 = [1,2,3]
let arr2 = [1,2,3]
delete arr1[1]
this.$delete(arr2,2)
console.log(arr1) //【1, empty, 3】
console.log(arr2) //【1,2】
computed和watch区别
computed 计算结果返回,只有当被计算的属性改变时触发。
watch 监听某个值,当被监听的值变化时,执行相关操作。