Vue学习笔记——Vue核心
📒Vue核心#
动态构建用户界面的渐进式JavaScript框架,遵循MVVM模式,编码简洁,体积小,运行效率高,适合移动/PC端开发,它本身只关注UI,也可以引入其它第三方库开发项目,借鉴Angular的模板和数据绑定技术,借鉴React的组件化和虚拟DOM技术.
📃模板语法#
html中包含了一些JS语法代码,语法分为两种
-
插值语法(双大括号表达式),用于解析标签体内容:
{{xxx}}
,xxxx会作为js表达式解析 -
指令(以v-开头),解析标签属性、解析标签体内容、绑定事件:
v-bind:href='xxxx'
,xxxx会作为js表达式被解析
📃数据绑定#
-
单向数据绑定,数据只能从data流向页面
v-bind:href="xxx"
或简写为:href
-
双向数据绑定,数据不仅能从data流向页面,还能从页面流向data
v-mode:value="xxx"
或简写为v-model="xxx"
✏️data与el的写法#
-
e1有2种写法
- newVue时候配置el属性.
- 先创建Vue实例,随后再通过vm.$mount('#root')指定el的值.
-
data有2种写法
-
对象式
-
函数式,用到组件时,data必须使用函数式
⚠️重要原则:由Vue管理的函数,一定不要写箭头函数,否则this就不再是Vue实例了.
-
📃MVVM模型#
- M:模型(Model):对应data中的数据
- V:视图(View):模板
- VM:视图模型(ViewModel):Vue实例对象
✏️数据代理#
-
Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
-
基本原理:
通过object.defineProperty()把data对象中所有属性添加到vm上.
为每一个添加到vm上的属性,都指定一个getter/setter.
在getter/setter内部去操作(读/写)data中对应的属性.
📃事件处理#
-
事件的基本使用:
- 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
- 事件的回调需要配置在methods对象中,最终会在vm上;
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象;
- @click="xxx”和 @chick="xxx($event)” 效果一致,但后者可以传参;
-
Vue中的事件修饰符(修饰符可连续写)
修饰符 作用 prevent 阻止默认事件; stop 阻止事件冒泡; once 事件只触发一次; capture 使用事件的捕获模式; self 只有event.target是当前操作的元素是才触发事件; passive 事件的默认行为立即执行,无需等待事件回调执行完毕; 📌冒泡是事件由子元素传递到父元素的过程;捕获事件由父元素传递到子元素的过程。
📌event.target是发生事件的元素或触发事件的元素。
📃计算属性#
-
定义:要用的属性不存在,要通过已有属性计算得来。
-
原理: 底层借助了objcet.defineproperty方法提供的getter和setter。
-
get函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。
-
优势: 与methods实现相比,内部有缓存机制(复用),效率更高,调试方便.
-
备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
-
计算属性简写
⚠️简写形式只考虑读取,不考虑修改
new Vue({ el:'#root', data:{ firstName:'张', lastName:'三', }, /*完整写法 computed:{ fullName:{ get(){ return this.firstName + '-' + this.lastName }, } } */ /*简写*/ computed:{ fullName(){ return this.firstName + '-' + this.lastName } } methods:{ //... } })
📃侦听属性#
-
当被监视的属性变化时,回调函数自动调用,进行相关操作(监视的属性存在时才能进行监视)
-
监视的两种写法:
- new Vue时传入watch配置
- 通过vm.$watch监视
-
深度监视:
- Vue中的watch默认不监测对象内部值的改变(一层)
- 配置deep:true可以监测对象内部值改变(多层)。
📌Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以,使用watch时根据数据的具体结构,决定是否采用深度监视.
new Vue({ el:"#root", data:{ numbers:{ a:1, b:2 } }, computed:{/*...*/}, methods:{/*...*/}, watch{ //监视多及结构中某个属性的变化 'numbers.a':{ handler(){/*...*/} }, //监视多及结构中所有属性的变化 numbers:{ deep:true, handler(){/*...*/} } } })
-
监听简写形式
⚠️配置项只有handler时适用
//... watch:{ /*完整写法 isHot:{ immediate:true,//初始化时让handler调用一下 deep:true,//深度监听 handler(newValue,oldValue){ //... } }, */ /*简写*/ isHot(newValue,oldValue){ //... } }
✏️watch对比computed#
-
computed和watch之间的区别:
tomputed能完成的功能,watch都可以完成。watch能完成的功能,computed不一定能完成.
🌰:watch可以进行异步操作。
//computed的错误写法,fullName没有返回值 data:{ firstName:'张', lastName:'三', }, computed:{ fullName(){ setTimeout(()=>{ return this.firstName + '-' + this.lastName },1000) } } // data:{ firstName:'张', lastName:'三', fullName:'张-三' }, watch:{ firstName(val){ setTimeout(()=>{ this.fullName = val + '-' + this.lastName },1000) } }
📌setTimeout并非Vue管理的函数,写成箭头函数使得setTimeout没有自己的this,从而往外找this,最后this指向Vue实例;若写成普通函数,this则指向windows。
-
两个重要的小原则:
⚠️所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象。
⚠️所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象。
📃绑定样式#
-
class样式的三种绑定方式
- 字符串写法,适用于样式的类名不确定,需要动态指定
- 数组写法,适用于要绑定的样式个数不确定,名字也不确定
- 对象写法,适用于要绑定的样式个数确定,名字也确定,但动态决定是否使用
-
style样式
:style="{fontsize: xxx]"
其中xxx是动态值。:style="[a,b]"
其中a、b是样式对象。
-
🌰
<head> <style> .basic {} .normal {} .happy {} .box1 {} .box2 {} .box3 {} </style> </head> <body> <div id="root"> <div class="basic" :class="mood" @click="changeMood">{{name}}</div> <div class="basic" :class="classArr">{{name}}</div> <div class="basic" :class="classObj">{{name}}</div> <div class="basic" :style="styleObj">{{name}}</div> <div class="basic" :style="styleArr">{{name}}</div> </div> </body> <script type="text/javascript"> new Vue({ el:'#root', data:{ name:'masahiko', mood:'normal', classArr:['box1','box2','box3'], classObj:{ box1:true, box2:false, }, styleObj:{ fontSize:'40px', color:'red', }, styleArr:[{ fontSize:'40px', color:'blue', },{ }] }, methods:{}, }) </script>
📃条件渲染#
-
v-if写法:
v-if="xxx"
v-else-if="xxx"
v-else="xxx"
(xxx为表达式)不展示的DOM元素直接被移除,适用于切换频率较低的场景.
-
v-show写法:
v-show="xxx"
不展示的DOM元素未被移除,仅仅是使用样式隐藏掉,适用于切换频率较高的场景。
📌使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
📃列表渲染#
-
v-for指令:
v-for="(item,index) in xxx :key="yyy"
用于展示列表数据,可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
✏️key的作用和原理#
-
虚拟DOM中key的作用
🔑是虚拟DOM对象的标识,当数据发生变化时,Vue会根据[新数据]生成[新的虚拟DOM]
随后Vue进行[新虚拟DOM]与[旧虚拟DOM]的差异比较,比较规则如下: -
对比规则
-
旧虚拟DOM中找到了与新虚拟DOM相同的key:
- 若虚拟DOM中内容没变,直接使用之前的真实DOM!
- 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
-
旧虚拟DOM中未找到与新的DOM相同的key:
创建新的真是DOM,随后渲染到页面。
-
-
用index作为key可能会引发的问题:
-
若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 => 界面效果没问题,但效率低。
-
如果结构中还包含输入类的DOM:
会产生错误DOM更新 => 界面有问题
-
-
开发中如何选择key
- 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值.
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
✏️Vue监视数据#
-
vue会监视data中所有层次的数据
-
通过setter实现监测对象中的数据,且要在new Vue时就传入要监测的数据。(_data中属性改变,引起属性所对应的setter调用,setter的调用能重新解析模板)
⚠️对象中后追加的属性,Vue默认不做响应式处理,如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)
vm.$set(target,propertyName/index, value)
-
通过包裹数组更新元素的方法实现监测数组中的数据,本质就是做了两件事:
- 调用原生对应的方法对数组进行更新。
- 重新解析模板,进而更新页面。
在Vue修改数组中的某个元素一定要用如下方法:
-
使用这些API:
push()
、pop()
、shift()
、unshift()
、splice()
、sort()
、reverse()
-
Vue.set
()或vm.$set()
⚠️特别注意:
Vue.set()
和vm.$set()
不能给vm或vm的根数据对象添加属性!!!
📃收集表单数据#
<input type="text"/>
:v-model收集的是value值,用户输入的就是value值。<input type="radio"/>
:v-model收集的是value值,且要给标签配置value值<input type="checkbox"/>
:- 没有配置input的value属性,那么收集的就是checked (勾选 or 未勾选,是布尔值)
- 配置input的value属性:
- v-model的初始值是非数组,那么收集的就是checked (勾选 or 未勾选,是布尔值)
- v-model的初始值是数组,那么收集的的就是value组成的数组
- v-model的三个修饰符:
- lazy: 失去焦点再收集数据
- number: 输入字符串转为有效的数字
- trim: 输入首尾空格过滤
📃过滤器#
- 对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
- 语法:
- 注册过滤器:
Vue.filter(name,callback)
或new Vue{filters:{}}
- 使用过滤器:
{{xxx | 过滤器名}}
或v-bind:属性 =“xxx | 过滤器名"
- 注册过滤器:
- 备注:
- 过滤器也可以接收额外参数、多个过滤器也可以串联
- 并没有改变原本的数据,是产生新的对应的数据
📃常用内置指令#
指令 | 作用 |
---|---|
v-bind | 单向绑定解析表达式,可简写为 :xxx |
v-model | 双向数据绑定 |
v-for | 遍历数组/对象/字符串 |
v-on | 绑定事件监听,可简写为@ |
v-if v-else |
条件渲染(动态控制节点是否存存在) |
v-show | 动态控制节点是否展示 |
v-text | 向其所在的节点中渲染文本内容 与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会。 |
v-html | 向指定节点中渲染包含html结构的内容 与插值语法的区别: (1).v-htm1会替换掉节点中所有的内容,{{xx}}则不会。 (2).v-htm1可以识别html结构。 |
v-cloak (没有值) |
特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性. 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。 |
v-once | 所在节点在初次动态渲染后,就视为静态内容了 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能 |
v-pre | 跳过其所在节点的编译过程。 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译. |
⚠️严重注意: v-html有安全性问题!
- 在网站上动态渲染任意html是非常危险的,容易导致XSS政击。
- 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
📃自定义属性#
-
定义语法:
-
局部指令:
new Vue({ directives:{指令名:配置对象} }) //或 new Vue({ directives{指令名:回调函数} })
-
全局指令
Vue.directive(指令名,配置对象) //或 Vue.directive(指令名,回调函数)
-
-
配置对象中常用的3个回调:
- bind:指令与元素成功绑定时调用。
- inserted: 指令所在元素被插入页面时调用。
- update:指令所在模板结构被重新解析时调用
-
备注:
- 指令定义时不加v-,但使用时要加v-;
- 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2022-01-28 JS犀牛书学习笔记——第三章 类型、值和变量