Vue2基础知识--第2节
十一、条件渲染
1.v-if
写法:
(1).v-if="表达式"
(2).v-else-if="表达式"
(3).v-else="表达式"
适用于:切换频率较低的场景。
特点:不展示的DOM元素直接被移除。
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
2.v-show
写法:v-show="表达式"
【底层dispaly:none】
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
3.备注
使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
十二、列表渲染
-
vue中对象用{ }
-
使用遍历,要使用key来标识,key不能相同
1、v-for指令
1.用于展示列表数据
2.语法:v-for="(item, index) in xxx" :key="yyy"
3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
- 面试题:react、vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
-
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
-
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
- 如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。
4.开发中如何选择key?:
-
最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
-
如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
2、Vue监视数据的原理
*1. vue会监视data中所有层次的数据。
*2. 如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
-
(1).对象中后追加的属性,Vue默认不做响应式处理
-
(2).如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)
或
vm.$set(target,propertyName/index,value)
*3. 如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
-
(1).调用原生对应的方法对数组进行更新。
-
(2).重新解析模板,进而更新页面。
*4.在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"/>
1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
2.配置input的value属性:
- (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
- (2)v-model的初始值是数组,那么收集的的就是value组成的数组
备注:v-model的三个修饰符:
-
lazy:失去焦点再收集数据
-
number:输入字符串转为有效的数字
-
trim:输入首尾空格过滤
十四、过滤器
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
语法:
1.注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
2.使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = “xxx | 过滤器名”
备注:
1.过滤器也可以接收额外参数、多个过滤器也可以串联
2.并没有改变原本的数据, 是产生新的对应的数据
bootcdn.cn
moment.js
day.js
十五、自定义指令
需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
自定义指令总结:
一、定义语法:
(1).局部指令: 【一个vue实例】
new Vue({
directives:{指令名:配置对象}
})
new Vue({
directives{指令名:回调函数}
})
(2).全局指令:
Vue.directive(指令名,配置对象)
或 Vue.directive(指令名,回调函数)
二、配置对象中常用的3个回调:
(1).bind:指令与元素成功绑定时调用。
(2).inserted:指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。
三、备注:
1.指令定义时不加v-,但使用时要加v-;
2.指令名如果是多个单词,要使用kebab-case【单词之间连字符连接】命名方式,不要用camelCase命名。
- 所有指令相关的回调this都是Windows,而不是对象
十六、生命周期
【生命周期!!特别重要】
-
又名:生命周期回调函数、生命周期函数、生命周期钩子。【等着vue调用】
-
是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
-
生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
-
生命周期函数中的this指向是vm 或 组件实例对象。
常用的生命周期钩子:
1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
- Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted 【第一次将东西放进页面,之后就是更新】
2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
// 动态样式用冒号
<h2 :style="{opacity}">欢迎学习Vue</h2>
//通过外部的定时器实现(不推荐)
/* setInterval(() => {
vm.opacity -= 0.01
if(vm.opacity <= 0) vm.opacity = 1
},16) */
undefined不显示在页面上
改vue中的data数据,就会重新解析模板
1、挂载流程
1.初始化事件和生命周期
生命周期函数有哪些,何时调用?
事件修饰符(一次性修饰符)如何处理?
data:{n:1} 此时vm还没收到,vm还没有_data
beforeCreate
无法通过vm访问到data中的数据、methods中的方法
2.初始化数据监测和数据代理
数据监测
数据代理
created
可以通过vm访问到data中的数据、methods中配置的方法
option指的是vm中的配置项
绿色是outerHTML,
beforeMount
将内存中的虚拟DOM转为真实的DOM插入页面
真实DOM结构保存在vm.$el身上
vm.$mount( elementOrSelector] )
mounted 【重要的钩子】
一上来要写的内容全部写在这里 【初始化的工作】
至此vue初始化过程结束,在此阶段:开启定时器、发送网络请求、订阅消息、绑定自定义事件等初始化操作
走没走过的选择:
template配置
div配置
2、更新流程
当data中的数据发生改变时,
beforeUpdate
数据是新的,但是页面是旧的,此时数据和页面没有保持同步
生成新的虚拟DOM,和旧的虚拟DOM 进行不比较,最终完成页面更新,model–view的更新
updated
数据和页面保持同步了
3、销毁流程
destroy销毁vm,vm的工作成果还在
vm.$destroy()
用法:
完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器【指的是自定义事件,点击事件是原生的DOM 事件】。
在大多数场景中你不应该调用这个方法。最好使用 v-if
和 v-for
指令以数据驱动的方式控制子组件的生命周期。
触发 beforeDestroy
和 destroyed
的钩子。
开发工具中vue中没有内容了
<h2 v-text='n'> </h2>
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁vm</button // 原生DOM事件并没有被销毁
beforeDestroy 【重要的钩子】
【收尾的工作】
vm中所有的data、methods、指令等,都处于可用状态,马上要执行销毁过程,对所有数据的更新不会触发更新了【在此处不要操作数据!!】,做一些收尾工作
destroyed
移除vm所有的监视、子组件和事件监听器【自定义事件】
【这个钩子用的最少!!!】
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
// 挂载完毕
// 大部分是挂载函数
mounted() {
console.log('mounted')
},
// 更新非常简单
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
// 可以调用数据,但对数据不进行更新
// 只进行收尾工作,对数据不进行相关操作
beforeDestroy() {
console.log('beforeDestroy')
},
destroyed() {
console.log('destroyed')
},
- 面试会问?
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
-
js对小数的处理欠缺,不擅长
-
红色是生命周期函数
-
不能作为根元素,
十七、非单文件组件(封装)
样式 结构 交互
1、Vue中使用组件的三大步骤
1、定义组件(创建组件)
2、注册组件
3、使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component(‘组件名’,组件)
三、编写组件标签:
<school></school>
几个注意点:
1.关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:
第二种写法:
备注:不用使用脚手架时【必须webpack配置环境,直接引用vue.js,不能】,会导致后续组件不能渲染。
3.一个简写方式:
const school = Vue.extend(options) 可简写为:const school = options
关于VueComponent:
1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
2.我们只需要写或,Vue解析时会帮我们创建school组件的实例对象,
即Vue帮我们执行的:new VueComponent(options)。
3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
4.关于this指向:
(1).组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
(2).new Vue(options)配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
1.一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
- 样式不能包括在组件中,要单拎出来
十八、单文件组件
vue不是HTML文件,包括
- HTML, 组件的结构
- css,
main.js文件:【入口文件】
- 创建vue实例,
App.vue文件:汇总所有组件
index.html文件:【页面】
- 引入main.js文件
组件划分按照功能;名字语义化一点;组件起名合理,组件是否拆分合理
组件之间的通信非常重要!!!!
.gitignore文件:
babel.config.js文件:重要,babel的控制文件,ES6->ES5,进行相关配置,直接使用官网的配置即可,
两个package文件:
1.配置好服务器;
2.打包文件,所有功能已经写完,最后的一次编译,将HTML和vue文件转换成HTML,css,js
3.lint将js和.vue文件进行语法检查,很少用
4.记录包的URL,很快下载
npm run serve命令执行后,就去运行main.js文件;
assets文件:存放静态资源,如图片、视频等
components文件夹:存放组件,除去pp
public/index.html是整个应用的界面
引入残缺版的vue:
1.残缺的vue不能写元素,那么使用render来创建元素,写模板render(createElement) {
return createElement(‘h1’, ‘你好啊’)
module是残缺的vue,完整版在dist/vue.js
2.vue两部分
-
核心
-
模板解析器,文件很大【精简版,打包时去除,runtime.js文件】
1、脚手架的默认配置
vue inspect > output.js
红色不要改,但是可以改
vue cli官网配置文件中写的配置可以改动
2、ref属性
给哪个元素绑定ref,vue就收集哪个元素的组件实例对象
3、全局事件总线
任意组件间通信;这是程序员的经验所得
x就是总线bus,vm和vc都能看到$bus;总线不能被同时占用,不能发生冲突
$on,$off,$emit在vue的原型对象上
整理不易,关注和收藏后拿走!
欢迎专注我的公众号:AdaCoding 和 Github:AdaCoding123