简单描述:虚拟 DOM(Virtual DOM)是一种轻量级的 JavaScript 对象,它描述了真实 DOM 中的节点信息和属性。虚拟 DOM 可以在内存中进行操作,然后通过算法比较新旧虚拟 DOM 的差异,最终只对发生变化的部分进行 DOM 操作,从而提高了性能。
diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁
响应式原理3个步骤:数据劫持、依赖收集、派发更新。
1、从 new Vue 开始,首先通过 get、set 监听 Data 中的数据变化,同时创建 Dep 用来搜集使用该 Data 的 Watcher。
2、编译模板,创建 Watcher,并将 Dep.target 标识为当前 Watcher。
3、编译模板时,如果使用到了 Data 中的数据,就会触发 Data 的 get 方法,然后调用 Dep.addSub 将 Watcher 搜集起来。
4、数据更新时,会触发 Data 的 set 方法,然后调用 Dep.notify 通知所有使用到该 Data 的 Watcher 去更新 DOM。
我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
对象在栈中存储的都是地址,函数的作用就是属性私有化,保证组件修改自身属性时不会影响其他复用组件。
不使用return包裹的数据会在项目的全局可见,会造成变量污染;使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。
Vue 的 nextTick 其本质是对 JavaScript 执行原理 EventLoop 的一种应用。
nextTick 的核心是利用了如 Promise 、MutationObserver、setImmediate、setTimeout的原生 JavaScript 方法来模拟对应的微/宏任务的实现,本质是为了利用 JavaScript 的这些异步回调任务队列来实现 Vue 框架中自己的异步回调队列。
单向数据流指只能从一个方向来修改状态
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
简单来说就是:子组件无法更改prop,只能通知父组件从而改变传递过来的prop。
1、通过后台来保存数据。
2、本地持久化。
3、通过vuex持久化。
4、通过url传递参数,保存在url中。
Vue2与Vue3 最大的区别:Vue2使用选项式API(Options API)对比Vue3组合式API(Composition API)
vue3 中使用了ES6 的 ProxyAPI 对数据代理,监测的是整个对象,而不再是某个属性。
基本上就是在 Vue2 生命周期钩子函数名基础上加了 on;beforeDestory 和 destoryed 更名为 onBeforeUnmount 和 onUnmounted;然后用setup代替了两个钩子函数 beforeCreate 和 created;新增了两个开发环境用于调试的钩子
若组件被包含,则多出下面两个钩子函
子组件通过defineProps()进行接收,并且接收这个函数的返回值进行数据操作。
总结: vue3 性能更高, 体积更小, 更利于复用, 代码维护更方便
Vue 在实例初始化时遍历 data 中的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。并 劫持各个属性 getter 和 setter,在数据变化时发布消息给订阅者,触发相应的监听回调,而这之间存在几个问题
Vue3 使用 Proxy 来监控数据的变化。Proxy 是 ES6 中提供的功能,其作用为:用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。相对于Object.defineProperty(),其有以下特点:
我们知道在数据变更触发页面重新渲染,会生成虚拟 DOM 并进行 patch 过程,这一过程在 Vue3 中的优化有如下
即就算不用composition API, 用 vue2 的写法也完全兼容!!
setup() 函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3的 Composition API 新特性提供了统一的入口, setup 函数会在 beforeCreate 、created 之前执行, vue3也是取消了这两个钩子,统一用setup代替, 该函数相当于一个生命周期函数,vue中过去的data,methods,watch等全部都用对应的新增api写在setup()函数中。
setup() 接收两个参数 props 和 context。它里面不能使用 this,而是通过 context 对象来代替当前执行上下文绑定的对象,context 对象有四个属性:attrs、slots、emit、expose
watch 作用是对传入的某个或多个值的变化进行监听;触发时会返回新值和老值;也就是说第一次不会执行,只有变化时才会重新执行。
watchEffect 是传入一个函数,会立即执行,所以默认第一次也会执行一次;不需要传入监听内容,会自动收集函数内的数据源作为依赖,在依赖变化的时候又会重新执行该函数,如果没有依赖就不会执行;而且不会返回变化前后的新值和老值。
共同点是 watch 和 watchEffect 会共享以下四种行为:
vue的跳转共分为6种
1、标签跳转 router-link
2、事件跳转 this.$router.push()
描述:跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。
3、this.$router.replace{path:‘/user’}
描述:同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。
4、this.$router.go(n)
描述:相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面。
5、this.router.forward() 前进一步
6、this.router.back() 回退一步
query传参:
1.可以使用name ,path , 字符串拼接方式传参
2.每次刷新不会丢失数据
3.不能使用props接收数据
params传参:
1.路由中不写占位符,只能使用name 传参
2.不使用占位符,刷新会丢失数据,使用占位符则不丢失数据 所以需要在规则中配置属性名
3.可以使用props接收数据
(扩展:params防止数据丢失)
在跳转到达的页面路由上这样写:
{
path: "/ordernoted/:id",//添加上要传递的参数
name: "ordernoted",
component: () => import("./views/ICK/Listpage/Ordernoted"),
meta: {
keepAlive: true
}
}
然后传参还是跟上面一样的方法传:
this.$router.push({
name:'ordernoted',
params:{
id:e.username
}
})
在下个页面接收:
var items =this.$route.params.id
console.log(items)
多个参数的话可以这样写:
path: "/ordernoted/:jum/:id",//可以一直在后边拼接参数
route是路由信息对象,每一个路由都会有一个route对象,是一个局部的对象,里面主要包含路由的一些基本信息
如:$route.name 当前路径名字、 r o u t e . m e t a 路由元信息、 route.meta 路由元信息、 route.meta路由元信息、route.path 字符串,对应当前路由的路径,总是解析为绝对路径
router是VueRouter的实例,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性
如: r o u t e r . g o ( ) 、 router.go()、 router.go()、router.push()
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:
slot又名插槽,通过插槽可以动态指定某一个组件模板部分的渲染, 我们在调用组件的时候, 在组件的调用标签中间传递了什么样的标签结构, 那么该组件就会把我们传递的标签结构放在他的模板部分进行渲染.。slot又分三类,默认插槽,具名插槽和作用域插槽。
hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
history: 它使用的是传统的路由分发模式,即用户在输入一个URL时,服务器会接收这个请求,并解析这个URL,然后做出相应的逻辑处理。
**abstract :**支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.
1、全局路由钩子
vue-router全局有三个路由钩子;
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
有五种,分别是 State、 Getter、Mutation 、Action、 Module
state:存放公共数据的地方;
getter:获取根据业务场景处理返回的数据;
mutations:唯一修改state的方法,修改过程是同步的;
action:异步处理,通过分发操作触发mutation;
module:将store模块分割,模块化,命名空间;
直接通过this.$store.getters和this.$store.state来访问模块中的getter和state。
直接通过this.$store.commit('mutationA',data)提交模块中的mutation。
直接通过this.$store.dispatch('actionA,data')提交模块中的action。
.prevent: 阻止默认事件;
.stop: 阻止冒泡;
.once: 事件执行一次;
.self: 只当在 event.target 是当前元素自身时触发处理函数
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端
SSR的优势:
1、使用DOM API直接找元素
Vue组件在patch阶段结束时会把this. e l 赋值为挂载的根 d o m 元素,我们可以直接使用 el赋值为挂载的根dom元素,我们可以直接使用 el赋值为挂载的根dom元素,我们可以直接使用el的querySelector, querySelectorAll等方法获取匹配的元素。
2、refs
使用组件实例的$refs即可拿到组件上ref属性对应的元素。
如果ref属性加在一个组件上,那么拿到的是这个组件的实例,否则拿到的就是dom元素了。
3、使用自定义指令
mounted()时才能获取