
本文共 5418 字,大约阅读时间需要 18 分钟。
系列文章目录
文章目录
为何组件的data必须是一个函数
Object是引用数据类型,如果不用function返回,每个组件的data都是内存的同一个地址,一个数据改变了其他也改变了,这就造成了数据污染。
vue常用指令:
v-model 多用于表单元素实现双向数据绑定
v-for 格式: v-for="(item,index) in/of 数组json" 循环数组或json v-show 显示内容 ,通过display=block/none来控制元素隐藏出现 v-hide 隐藏内容 同上 v-if 显示与隐藏 (dom元素的删除添加 同angular中的ng-if 默认值为false) v-else-if 必须和v-if连用 v-else 必须和v-if连用 不能单独使用 否则报错 模板编译错误 v-bind 动态绑定 作用: 及时对页面的数据进行更改 v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在methods里面 v-text 解析文本 v-html 解析html标签 v-bind:class 三种绑定方法 1、对象型 ‘{red:isred}’ 2、三元型 ‘isred?“red”:“blue”’ 3、数组型 ‘[{red:“isred”},{blue:“isblue”}]’ v-once 进入页面时 只渲染一次 不在进行渲染 v-cloak 防止闪烁 该属性需配合 样式使用: v-pre 把标签内部的元素原位输出v-if与v-show的区别
相同点:
都可以动态控制着dom元素的显示隐藏
区别:
v-if: 控制DOM元素的显示隐藏是将DOM元素整个添加或删除;
v-show: 控制DOM 的显示隐藏是为DOM元素添加css的样式display,设置none或者是block,DOM元素是还存在的
性能相比:
v-if有更高的切换消耗;
v-show有更高的初始渲染消耗
v-show适合频繁切换;
Vue生命周期钩子函数
1.创建 beforeCreate created
beforeCreate() 创建前的阶段,这个时候data中的数据,还未定义,所以不能使用 created() 最早开始使用 data和methods中数据的钩子函数
2.挂载 beforeMount mounted
beforeMount() 指令已经解析完毕内存中已经生成dom树,还没有渲染到本地 mounted() dom已经渲染完毕,最早可以操作DOM元素钩子函数
3.更新 beforeUpdate updated
beforeUpdate() 当data的数据发生改变会执行这个钩子 内存更新,但是DOM节点还未更新 updated() 数据更新完成以后触发的方法,DOM节点已经更新
4.销毁 beforeDestroy destroyed
beforeDestroy()即将销毁 data和methods中的数据此时还是可以使用的,可以做一些释放内存的操作 destroyed()已经销毁完毕
5.缓存:
activated – 组件激活时执行deactivated – 组件停用时执行
6.错误处理:
errorCaptured – 错误处理机制
Vue的双向数据绑定原理(简洁版)
核心思想通过Object.defineProperty来对Vue的数据进行数据劫持,
主要分为三部分 :observer主要是负责对Vue数据进行数据劫持,使其数据拥有get和set方法
compile模板解析 (指令解析器负责绑定数据和指令,绑定试图更新方法 )
watcher负责数据监听,当数据发生改变通知订阅者,调用视图更新函数更新视图
Vue中的虚拟dom,diff 算法
虚拟dom
虚拟DOM 表现为一个 Object对象。并且最少包含标签名 (tag)、属性 (attrs) 和子元素对象 (children) 三个属性创建虚拟DOM就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM对象的节点与真实DOM的属性一一照应
通过VNode,vue可以对这颗抽象树进行创建节点,删除节点以及修改节点的操作,经过diff算法得出一些需要修改的最小单位,再更新视图,减少了dom操作,提高了性能
diff 算法
1.用js对象来表示真是的DOM树结构,创建一个虚拟DOM对象2.当数据发生改变的时候,创建一个新的js的虚拟DOM对象3.比较新旧对象的差异,记录下来,最终更新到真实的DOM树结构上。总结:总的来说就是减少DOM,重绘和回流。
Vue组件通信
在vue中有很多传参方式,包括子传夫,夫传子,兄弟传,路由传参,vuex等等…
什么是vuex?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它由五部分组成:
分别是:state,actions,mutations,getters,modulesvuex的核心概念有五部分组成
- state: 所有的数据都存在state中,state可以数组也可以是对象
- actions:可以包含异步操作,只能调用mutations中的方法
- mutations: 唯一可以修改state数据的场所
- getters: 类似于vue组件中的计算属性,对state数据进行计算(会被缓存)
- modules:模块化管理store(仓库),每个模块拥有自己的 state、mutation、action、getter
Vue的运行机制
在组件中通过dispatch来调用actions中的方法,在actions中调用commit来调用mutations中的方法,在mutations中可以直接操作state中的数据,satat中的数据只要发生改变立马响应到组件中vue中Computed、Methods、Watch区别
computed 具有缓存性,依赖于属性值,只有属性发生改变的时候才会重新调用
methods 是没有缓存的,只要调用,就会执行,一般结合事件来使用
watch 没有缓存性 监听data中的属性 属性值只要发生变化就会执行 可以利用他的特性做一些异步的操作
vue中的修饰符
.stop 阻止事件继续传播
.prevent 阻止标签默认行为 .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 .self 只当在 event.target 是当前元素自身时触发处理函数 .once 事件将只会触发一次 .passive 告诉浏览器你不想阻止事件的默认行为vue修改数据页面不重新渲染
原因:组件初始化时,对data中的item进行递归遍历,对item的每一个属性进行劫持,添加set,get方法。我们后来新加的newProperty属性,并没有通过Object.defineProperty设置成响应式数据,修改后不会视图更新。
解决方案:
Vue 不允许在已经创建的实例上动态添加新的响应式属性若想实现数据与视图同步更新,可采取下面三种解决方案:
- Vue.set()
- Object.assign()
- $forcecUpdated()
Vue.set()
参数: target:要修改的对象或数组 propertyName/index:属性或下标 value:修改后的value值this.$set(this.item, "newProperty", "新值");
再次调用defineReactive方法,实现新增属性的响应式,
关于defineReactive方法,内部还是通过Object.defineProperty实现属性拦截
Object.assign()
直接使用Object.assign()添加到对象的新属性不会触发更新应创建一个新的对象,合并原对象和混入对象的属性
this.item = Object.assign({ },this.item,{ newProperty:'新值'})
$forceUpdate
如果你发现你自己需要在 Vue中做一次强制更新,99.9% 的情况,是你在某个地方做错了事$forceUpdate迫使Vue 实例重新渲染
PS:仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
this.item.newProperty = "新值" this.$forceUpdate();
小结
- 如果为对象添加少量的新属性,可以直接采用Vue.set()
- 如果需要为新对象添加大量的新属性,则通过Object.assign()创建新对象
- 如果你需要进行强制刷新时,可采取$forceUpdate() (不建议) PS:vue3是用过proxy实现数据响应式的,直接动态添加新属性仍可以实现数据响应式
Vue中的$nextTick()
它本质是一种优化策略,我们可以理解成,Vue 在更新 DOM时是异步执行的。当数据发生变化,Vue将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新。
为什么要有nexttick
举个例子
{ { num}}for(let i=0; i<100; i++){ num = i}
如果没有 nextTick 更新机制,那么 num每次更新值都会触发视图更新(上面这段代码也就是会更新100次视图),有了nextTick机 制,只需要更新一次
keep-alive
作用
在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性Vue 中怎么自定义过滤器
可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值。
Vue.filter('reverse', function (value) { return value.split('').reverse().join('')})
vue组件封装
每个 .vue单文件就是一个组件。在另一组件import 导入,并在components中注册,子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。
v-for中为何要使用key
key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点
v-if和v-for的优先级
v-if vs v-show
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
v-if 与 v-for一起使用
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。请查阅列表渲染指南以获取详细信息。
axios的封装
步骤如下:
安装
npm install axios; // 安装axios
引入
一般我会在项目的src目录中,新建一个request文件夹,然后在里面新建一个http.js和一个api.js文件。http.js文件用来封装我们的axios,api.js用来统一管理我们的接口。
http.js操作如下:
import axios from 'axios';const request = axios.create({ // baseURL: 'http://39.100.7.70:81/', timeout: 5000});request.interceptors.request.use(config=>{ return config});request.interceptors.response.use(config=>{ return config});export default request
api.js操作如下:
import request from "@/utils/request"export default { getDetails(data = { }) { return request({ url: "/api/product/getDetails", method: "POST", data: data }) },}
后续更新…