为什么mutation⾥⾯只能同步,不能异步?23
牧一征
就会⽅便追踪到state的变化,因为state⾥⾯的数据会改变异步的话组件有可能会收不到,不能实时追踪
严格模式会报错
页⾯刷新后vuex的state数据丢失怎么解决?
将Vuex⾥的数据同步更新到localStorage⾥。
层压钢板即:⼀改变vuex⾥的数据,便触发localStorage.setItem⽅法
在App.vue的created钩⼦函数⾥写
//在页⾯加载时读取localStorage⾥的状态信息
//在页⾯刷新时将vuex⾥的信息保存到localStorage⾥
window.addEventListener("beforeunload",()=>{
localStorage.setItem("userMsg",JSON.stringify(this.$store.state))
})
store提供了哪些函数
提供getState( )⽅法获取state;
提供dispatch(action)⽅法更新state;
通过subscribe(listener)注册;
通过subscribe(listener)返回的函数注销
使⽤ mapState⼯具函数会将store中的state映射到局部计算属性中
mapGetter,mapMutation,mapAction会将store中各⾃的⽅法映射过来
vuex是什么呢?哪些场景会⽤到?
vuex是⼀个专为vue.js应⽤程序开发的状态管理模式
我们⼤概可以理解为vuex是⼀个公共状态库 , 你可以在所有的组件⾥⾯去使⽤,修改
场景有:单页应⽤中,组件之间的状态、⾳乐播放、登录状态、加⼊购物车
vuex为状态管理,它集中存储管理应⽤的所有组件的状态,可以理解成⼀个全局仓库
VueRouter是路由(spa)单页⾯应⽤的⽅式
使⽤vuex的优势是什么?有⽤过vuex吗?它主要解决的是什么问题?
Vuex的优势:
1.解决了⾮⽗⼦组件的消息传递(将数据存放在state中)
2.减少了AJAX请求次数,有些情景可以直接从内存中的state获取
主要解决的问题是:
⽤来管理全局的组件状态,⽐如有很多个组件都会修改同⼀个数据,同时这个数据⼜要在多个组件上同时显⽰,这个时候⽤ vuex 来统⼀管理这些组件的状态,会让逻辑更清晰,更可维护
vue和react渲染有什么区别
vue---会跟踪每⼀个组件的依赖关系, 去重新渲染有依赖关系的组件,不是说重新渲染整个组件树。
react--如果某个组件状态发⽣变化,react会把这个组件还有这个组件的所有后代组件全部重新渲染,不过重新渲染并不是代表全部丢掉上⼀次的渲染结果,react通过diff去⽐较两次虚拟dom,⽐较之后再反映倒真实dom上,如果说组件树⽐较⼤,diff算法也是⼀⽐开
销,react提供出来解决⽅案shouldComponentUpdate-----根据这个⽣命周期的返回结果来判断是不是需要执⾏后⾯的diff,update这些东西;
vue---Object.defineProperty get去收集依赖,因此不会像react- 样去⽐较整颗组件树,去更加细粒度的去更新状态有变化的组件;
vue中路由的模式如何选择,不同模式有什么区别?
Hash模式
就是 Hash URL,当 # 后⾯的哈希值发⽣变化时,可以通过 hashchange 事件来监听到 URL 的变化,从⽽进⾏跳转页⾯,并且⽆论哈希值如何变化,服务端接收到的 URL 请求永远是。
window.addEventListener('hashchange', () => {
// ... 具体逻辑
})
Hash 模式相对来说更简单,并且兼容性也更好。
History模式
History 模式是 HTML5 新推出的功能,主要使⽤ history.pushState 和 placeState改变 URL。
通过 History 模式改变 URL 同样不会引起页⾯的刷新,只会更新浏览器的历史记录。
// 新增历史记录
history.pushState(stateObject, title, URL)
// 替换当前历史记录
当⽤户做出浏览器动作时,⽐如点击后退按钮时会触发 popState 事件
window.addEventListener('popstate', e => {
// e.state 就是 pushState(stateObject) 中的 stateObject
console.log(e.state)
})
两种模式对⽐
· Hash 模式只可以更改 # 后⾯的内容,History 模式可以通过 API 设置任意的同源 URL
· History 模式可以通过 API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串
· Hash 模式⽆需后端配置,并且兼容性好。History 模式在⽤户⼿动输⼊地址或者刷新页⾯的时候会发起 URL 请求,后端需要配置index.html 页⾯⽤于匹配不到静态资源的时候
$route和$router有什么区别,有什么关联关系
1. $router 为 VueRouter 实例,想要导航到不同 URL,则使⽤ $router.push ⽅法。 $route 为当前 rou
ter 跳转对象⾥⾯可以获取
name 、 path 、 query 、 params 等。
插槽slot
插槽(Slot)插槽⽤于决定将所携带的内容,插⼊到指定的某个位置,从⽽使模板分块,具有模块化的特质和更⼤的重⽤性,插槽就
是Vue实现的⼀套内容分发的API
1.匿名插槽:叫做默认插槽就是没有名字
2.具名插槽:需要多个插槽时,可以利⽤元素的⼀个特殊的特性:name来定义具名插槽
3.作⽤域插槽:是⽗组件引⽤⼦组件中的数据,使⽤slot-scope 进⾏数据的传递,⼦组件中将数据传递给⽗组件
v-for和v-if的优先级
v-for的优先级⾼于v-if
watch
watch的原理通过watch的⽅法,监听被改变的变量,然后再watch的那个变量命名的函数中去对我们要修改的值进⾏重新的赋值,或者是触发⼀次更新。 watch的执⾏类似于emit与on这种触发⽅式,通过vue的watch实例监听值来⾃动触发⼀个函数的执⾏。
· watch函数的参数中,第⼀个是改变之前的值,第⼆个是改变之后的值,这两个参数⾮常有⽤。
· 这⾥分别使⽤了三种定义函数(或option)的⽅法。
· 如果要观察data下⼀个对象的属性,我们可以使⽤对象.属性的⽅式,注意:⼀定要要引号。
· 如果改变了⼀个对象的属性,就必须使⽤deep: true,否则检测不到变化。
watch和computed差异
watch是进⾏数据监听,然后进⾏相应的操作,执⾏⽅法等conputed和methods的合体使⽤,⽐较耗性能,与vue性能优化相背⽽驰,尽量减少使⽤!computed是数据改变进⾏相应的数据变化,由⽼数据迸发新的数据(return返回),会利⽤缓存机制对数据进⾏缓存,只有当依赖数据变化的时候才会进⾏相应的变化
跨域
组件 data 为什么必须是函数
因为 JS 本⾝的特性带来的,如果 data 是⼀个对象,那么由于对象本⾝属于引⽤类型,当我们修改其中的⼀个属性时,会影响到所有 Vue 实例的数据。如果将 data 作为⼀个函数返回⼀个对象,那么每⼀个实例的 data 属性都是独⽴的,不会相互影响了。
$nextTick
$nextTick 是在下次 DOM 更新循环结束之后执⾏延迟回调,在修改数据之后使⽤ $nextTick,则可以在回调中获取更新后的 DOM。
key
key的作⽤是为了在diff算法执⾏时更快的到对应的节点,提⾼diff速度
key具有唯⼀性,使⽤ key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。有相同⽗元素的⼦元素必须有独特的 key。重复的 key 会造成渲染错误。
带key就不会使⽤就地复⽤了,在sameNode函数a.key===b.key对⽐中可以避免就地复⽤的情况。
叉车防撞UWB
vue中列表循环需加:key="唯⼀标识" 唯⼀标识可以是item⾥⾯id index等,因为vue组件⾼度复⽤增加Key可以标识组件的唯⼀性,为了更好地区别各个组件 key的作⽤主要是为了⾼效的更新虚拟DOM
可以这样简单地理解,⽆:key属性时,状态默认绑定的是位置;有:key属性时,状态根据key的属性值绑定到了相应的数组元素。
若⽤数组索引index为key,当向数组中指定位置插⼊⼀个新元素后,对应着后⾯的虚拟DOM的key值全部更新了,这个时候还是会做不必要的更新,就像没有加KEY⼀样
为什么官⽹说的是就地更新的效率更⾼呢
key的作⽤就是更新组件时判断两个节点是否相同。相同就复⽤,不相同就删除旧的创建新的。在渲染简单的⽆状态组件时,如果不添
加key组件默认都是就地复⽤,不会删除添加节点,只是改变列表项中的⽂本值,要知道节点操作是⼗分耗费性能的。⽽添加了key之后,当对⽐内容不⼀致时,就会认为是两个节点,会先删除掉旧节点,然后添加新节点。
vue图⽚懒加载
vue-lazyload
vue路由懒加载
⽅法⼀ resolve
这⼀种⽅法较常见。它主要是使⽤了resolve的异步机制,⽤require代替了import,实现按需加载,下⾯是代码⽰例:
import Vue from'vue'
import Router from'vue-router'
// import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
// {
// path: '/',
// name: 'HelloWorld',
// component: HelloWorld
// }
{
path: '/',
name: 'HelloWorld',
component: resolve =>require(['@/components/HelloWorld'], resolve)
}
]
})
⽅法⼆
vue-router在官⽹提供了⼀种⽅法,可以理解也是为通过Promise的resolve机制。因为Promise函数返回的Promise为resolve组件本⾝,⽽我们⼜可以使⽤import来导⼊组件。整合起来代码⽰例如下: