渐进式javacript框架, 一套拥有自己规则的语法
Vue 是一套用于构建用户界面的渐进式框架. 与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
Vue.js 是前端的主流框架之一,和 Angular.js、React.js 一起,并成为前端三大主流框架
官网地址: Vue.js - 渐进式 JavaScript 框架 | Vue.jsVue.js - 渐进式的 JavaScript 框架https://cn.vuejs.org/ (作者: 尤雨溪)
渐进式
声明式渲染
数据驱动视图 (响应式)
极少的去写DOM操作相关代码
双向绑定
组件系统
不兼容IE8及以下浏览器
1.体积小
2.更高的运行效率
3.双向数据绑定,简化 Dom 操作
通过 MVVM 思想实现数据的双向绑定
4 生态丰富、学习成本低
市场上拥有大量成熟、稳定的基于 vue.js 的 ui 框架、常用组件 来即用实现
快速开发 对初学者友好、入门容易、学习资料多.
@vue/cli是Vue官方提供的一个全局模块包(得到vue命令), 此包用于创建脚手架项目
脚手架是为了保证各施工过程顺利进行而搭设的工作平台
@vue/cli的好处
开箱即用
0配置webpack
babel支持
css, less支持
开发服务器支持
目标: 把@vue/cli模块包按到全局, 电脑拥有vue命令, 才能创建脚手架工程
yarn global add @vue/cli # OR npm install -g @vue/cli
注意: 如果半天没动静(95%都是网速问题), 可以ctrl c停止重新来,换一个网继续重来
vue
脚手架版本vue -V
总结: 如果出现版本号就安装成功, 否则失败
目标: 使用vue命令, 创建脚手架项目
# vue和create是命令, vuecli-demo是文件夹名
vue create vuecli-demo
注意: 项目名不能带大写字母, 中文和特殊符号
cd vuecil-demo
npm run serve
# 或
yarn serve
只要看到绿色成功了(底层node+webpack热更新服务)
vuecil-demo # 项目目录
├── node_modules # 项目依赖的第三方包
├── public # 静态文件目录
├── favicon.ico# 浏览器小图标
└── index.html # 单页面的html文件(网页浏览的是它)
├── src # 业务文件夹
├── assets # 静态资源
└── logo.png # vue的logo图片
├── components # 组件目录
└── HelloWorld.vue # 欢迎页面vue代码文件
├── App.vue # 整个应用的根组件
└── main.js # 入口js文件
├── .gitignore # git提交忽略配置
├── babel.config.js # babel配置
├── package.json # 依赖包列表
├── README.md # 项目说明
└── yarn.lock # 项目包版本锁定和缓存地址
主要文件及含义
node_modules下都是下载的第三方包
public/index.html – 浏览器运行的网页
src/main.js – webpack打包的入口文件
src/App.vue – vue项目入口页面
package.json – 依赖包列表文件
目标:项目中没有webpack.config.js文件,因为@vue/cli用的vue.config.js
src并列处新建vue.config.js
/* 覆盖webpack的配置 */
module.exports = {
devServer: { // 自定义服务配置
open: true, // 自动打开浏览器
port: 3000
}
}
目标: 知道eslint的作用, 和如何暂时关闭, 它是一个代码检查工具
演示: 在main.js中随便定义变量 – 不使用 – 观察eslint报错
方式1: 手动解决掉错误, 以后项目中会讲如何自动解决
方式2: 暂时关闭eslint检查(因为现在主要精力在学习Vue语法上), 在vue.config.js中配置后重启服务
目标: 单vue文件好处, 独立作用域互不影响
Vue推荐采用.vue文件来开发项目
template里只能有一个根标签
vue文件-独立模块-作用域互不影响
style配合scoped属性, 保证样式只针对当前template内标签生效
vue文件配合webpack, 把他们打包起来插入到index.html
欢迎使用vue
最终: Vue文件配合webpack, 把他们打包起来插入到index.html, 然后在浏览器运行
单vue文件好处?
独立作用域, 不再担心变量重名问题
(1)assets 和 components 文件夹下的一切都删除掉 (不要默认的欢迎页面)
(2)src/App.vue默认有很多内容, 可以全部删除留下template和script和style的框
目的: 转变思维, 用数据驱动视图改变, 操作dom的事, vue源码内操作了
设计模式: 是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
MVVM,一种软件架构模式,决定了写代码的思想和层次
M: model数据模型 (data里定义)
V: view视图 (html页面)
VM: ViewModel视图模型 (vue.js源码)
MVVM通过数据双向绑定
让数据自动地双向同步 不再需要操作DOM
V(修改视图) -> M(数据自动同步)
M(修改数据) -> V(视图自动同步)
总结: vue源码内采用MVVM设计模式思想, 大大减少了DOM操作, 挺高开发效率
mvvm和mvc区别是什么?
MVC: 也是一种设计模式, 组织代码的结构, 是model数据模型, view视图, Controller控制器,
在控制器这层里编写js代码, 来控制数据和视图关联
MVVM: 即Model-View-ViewModel的简写。即模型-视图-视图模型, VM是这个设计模式的核心,
连接v和m的桥梁, 内部会监听DOM事件, 监听数据对象变化来影响对方. 我们称之为数据绑定
目的: 在dom标签中, 直接插入内容
又叫: 声明式渲染/文本插值
语法: {{ 表达式 }}
msg和obj是vue数据变量
要在js中data函数里声明
{{ msg }}
{{ obj.name }}
{{ obj.age > 18 ? '成年' : '未成年' }}
总结: dom中插值表达式赋值, vue的变量必须在data里声明
目标: 给标签属性设置vue变量的值
vue指令, 实质上就是特殊的 html 标签属性, 特点: v- 开头
每个指令, 都有独立的作用
语法:v-bind:属性名="vue变量"
简写::属性名="vue变量"
我是a标签
总结: 把vue变量的值, 赋予给dom属性上, 影响标签显示效果
目标: 给标签绑定事件
语法
v-on:事件名="要执行的==少量代码=="
v-on:事件名="methods中的函数"
v-on:事件名="methods中的函数(实参)"
简写: @事件名="methods中的函数"
你要买商品的数量: {{count}}
总结: 常用@事件名, 给dom标签绑定事件, 以及=右侧事件处理函数
练习-翻转世界
目标: 点击按钮 - 把文字取反显示 - 再点击取反显示(回来了)
提示: 把字符串取反赋予回去
{{ message }}
目标: vue事件处理函数中, 拿到事件对象
语法:
无传参, 通过形参直接接收
传参, 通过$event指代事件对象传给事件处理函数
目的: 在事件后面.修饰符名 - 给事件带来更强大的功能
语法:
@事件名.修饰符="methods里函数"
.stop - 阻止事件冒泡
.prevent - 阻止默认行为
.once - 程序运行期间, 只触发一次事件处理函数
总结: 修饰符给事件扩展额外功能
目标: 给键盘事件, 添加修饰符, 增强能力
语法:
@keyup.enter - 监测回车按键
@keyup.esc - 监测返回按键
更多修饰符https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E4%BF%AE%E9%A5%B0%E7%AC%A6
总结: 多使用事件修饰符, 可以提高开发效率, 少去自己判断过程
目标: 把value属性和vue数据变量, 双向绑定到一起
语法: v-model="vue数据变量"
双向数据绑定
数据变化 -> 视图自动同步
视图变化 -> 数据自动同步
演示: 用户名绑定 - vue内部是MVVM设计模式
用户名:
密码:
来自于:
爱好:
抽烟
喝酒
写代码
性别:
男
女
自我介绍
总结: 本阶段v-model只能用在表单元素上, 以后学组件后讲v-model高级用法
目标: 让v-model拥有更强大的功能
语法:
v-model.修饰符="vue数据变量"
.number 以parseFloat转成数字类型
.trim 去除首尾空白字符
.lazy 在change时触发而非inupt时
年龄:
人生格言:
自我介绍:
总结: v-model修饰符, 可以对值进行预处理, 非常高效好用
目的: 更新DOM对象的innerText/innerHTML
语法:
v-text="vue数据变量"
v-html="vue数据变量"
注意: 会覆盖插值表达式
总结: v-text把值当成普通字符串显示, v-html把值当做html解析
目标: 控制标签的隐藏或出现
语法:
v-show="vue变量"
v-if="vue变量"
原理
v-show 用的display:none隐藏 (频繁切换使用)
v-if 直接从DOM树上移除
高级
v-else使用
v-show的盒子
v-if的盒子
我成年了
还得多吃饭
总结: 使用v-show和v-if以及v-else指令, 方便通过变量控制一套标签出现/隐藏
案例-折叠面板
目标: 点击展开或收起时,把内容区域显示或者隐藏
此案例使用了less语法, 项目中下载模块
yarn add [email protected] [email protected] -D
案例:折叠面板
芙蓉楼送辛渐
{{ isShow ? '收起' : '展开' }}
寒雨连江夜入吴,
平明送客楚山孤。
洛阳亲友如相问,
一片冰心在玉壶。
目标: 列表渲染, 所在标签结构, 按照数据数量, 循环生成
语法
v-for="(值, 索引) in 目标结构"
v-for="值 in 目标结构"
目标结构:
可以遍历数组 / 对象 / 数字 / 字符串 (可遍历结构)
注意:
v-for的临时变量名不能用到v-for范围外
学生姓名
-
{{ index }} - {{ item }}
学生详细信息
-
{{ obj.name }}
{{ obj.sex }}
{{ obj.hobby }}
老师信息
{{ key }} -- {{ value }}
序号
{{ i }}
总结: vue最常用指令, 铺设页面利器, 快速把数据赋予到相同的dom结构上循环生成
为什么避免v-for和v-if在一起使用
Vue 处理指令时,v-for 比 v-if 具有更高的优先级, 虽然用起来也没报错,
但是性能不高, 如果你有5个元素被v-for循环, v-if也会分别执行5次.
练习-购物车
目标: 完成商品浏览和删除功能, 当无数据给用户提示
需求1: 根据给的初始数据, 把购物车页面铺设出来
需求2: 点击对应删除按钮, 删除对应数据
需求3: 当数据没有了, 显示一条提示消息
编号
品牌名称
创立时间
操作
{{item.id}}
{{item.name}}
{{item.time}}
没有数据咯~
目标: 当v-for遍历的目标结构改变, Vue触发v-for的更新
情况1: 数组翻转
情况2: 数组截取
情况3: 更新值
口诀:
数组变更方法, 就会导致v-for更新, 页面更新
数组非变更方法, 返回新数组, 就不会导致v-for更新, 可采用覆盖数组或this.$set()
这些方法会触发数组改变, v-for会监测到并更新页面
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
这些方法不会触发v-for更新
slice()
filter()
concat()
-
{{ val }}
注意: vue不能监测到数组里赋值的动作而更新, 如果需要请使用Vue.set() 或者this.$set(), 或者覆盖整个数组
总结: 改变原数组的方法才能让v-for更新
v-for
的默认行为会尝试原地修改元素而不是移动它们。
详解v-for就地更新流程
这种虚拟DOM对比方式(同级对比,标签与标签对比,相同则复用), 可以提高性能 - 但是还不够高
a. .vue文件中的template里写的标签, 都是模板, 都要被vue处理成虚拟DOM对象, 才会渲染显示到真实DOM页面上
b. 内存中生成一样的虚拟DOM结构(本质是个JS对象)
- 生成新的虚拟DOM结构
- 和旧的虚拟DOM结构对比
- 利用diff算法, 找不不同, 只更新变化的部分(重绘/回流)到页面 - 也叫打补丁
好处1: 提高了更新DOM的性能(不用把页面全删除重新渲染)
好处2: 虚拟DOM只包含必要的属性(没有真实DOM上百个属性)
总结: 虚拟DOM保存在内存中, 只记录dom关键信息, 配合diff算法提高DOM更新的性能
在内存中比较差异, 然后给真实DOM打补丁更新上
vue用diff算法, 新虚拟dom和旧的虚拟dom比较
情况1: 根元素变了, 删除重建
旧虚拟DOM
123
新虚拟DOM
- 123
情况2: 根元素没变, 属性改变, 元素复用, 更新属性
旧虚拟DOM
123
新虚拟DOM
123
情况3: 根元素没变, 子元素没变, 元素内容改变
-
{{ str }}
export default {
data(){
return {
arr: ["老大", "新来的", "老二", "老三"]
}
},
methods: {
addFn(){
this.arr.splice(1, 0, '新来的')
}
}
};
旧虚拟DOM结构 和 新虚拟DOM结构 对比过程
性能不高, 从第二个li往后都更新了
有key属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素
先产生新旧虚拟DOM, 根据key比较, 因为新旧虚拟DOM对比, key存在就复用此标签更新内容, 如果不存在就直接建立一个新的,因此还是就地更新
-
{{ str }}
export default {
data(){
return {
arr: ["老大", "新来的", "老二", "老三"]
}
},
methods: {
addFn(){
this.arr.splice(1, 0, '新来的')
}
}
};
v-for先循环产生新的DOM结构, key是连续的, 和数据对应
然后比较新旧DOM结构, 找到区别, 打补丁到页面上
最后补一个li, 然后从第二个往后, 都要更新内容
key的值只能是唯一不重复的, 字符串或数值
v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM,
需要用特殊 attribute key 来提供一个排序提示
新DOM里数据的key存在, 去旧的虚拟DOM结构里找到key标记的标签, 复用标签
新DOM里数据的key存在, 去旧的虚拟DOM结构里没有找到key标签的标签, 创建
旧DOM结构的key, 在新的DOM结构里没有了, 则==移除key所在的标签
-
{{ obj.name }}
先产生新旧虚拟DOM, 根据key比较
总结: 不用key也不影响功能(就地更新), 添加key可以提高更新的性能
目标: 用v-bind给标签class设置动态的值
语法:
:class="{类名: 布尔值}"
动态class
总结: 就是把类名保存在vue变量中赋予给标签
目标: 给标签动态设置style的值
动态style
总结: 动态style的key都是css属性名
案例-品牌管理
需求1: 把默认数据显示到表格上
需求2: 注意资产超过100的, 都用红色字体标记出来
实现数据增删
细节:
① 先铺设静态页面
② 此案例使用bootstrap, 需要下载, 并导入到工程main.js中
bootstrap, 工程化开发, 模块化用npm/yarn下载引入使用
arn add bootstr
在main.js - 引入bootstrap
import "bootstrap/dist/css/bootstrap.css"
// 默认找文件夹下的index文件(但是这个不是所以需要写路径)
③ 用v-for配合默认数据, 把数据默认铺设到表格上显示
④ 直接在标签上, 大于100价格, 动态设置red类名
品牌管理
编号
资产名称
价格
创建时间
操作
{{ obj.id }}
{{ obj.name }}
{{ obj.price }}
{{ obj.time }}
删除
目的: 转换格式, 过滤器就是一个函数, 传入值返回处理后的值
例子:
全局定义字母都大写的过滤器
局部定义字符串翻转的过滤器
原来的样子: {{ msg }}
使用翻转过滤器: {{ msg | reverse }}
鼠标长停
总结: 把值转成另一种形式, 使用过滤器, Vue3用函数替代了过滤器.
全局注册最好在main.js中注册, 一处注册到处使用
目标: 可同时使用多个过滤器, 或者给过滤器传参
语法:
过滤器传参: vue变量 | 过滤器(实参)
多个过滤器: vue变量 | 过滤器1 | 过滤器2
原来的样子: {{ msg }}
使用翻转过滤器: {{ msg | reverse('|') }}
鼠标长停
总结: 过滤器可以传参, 还可以对某个过滤器结果, 后面在使用一个过滤器
(1)下载moment处理日期的第三方工具模块
moment官网文档: Moment.js 中文网 | 开发文档
yarn add moment
(2)定义过滤器, 把时间用moment模块格式化, 返回我们想要的格式
// 目标: 处理时间
// 1. 下载moment模块
import moment from 'moment'
// 2. 定义过滤器, 编写内部代码
filters: {
formatDate (val){
return moment(val).format('YYYY-MM-DD')
}
}
{{ obj.time | formatDate }}
目标: 一个数据, 依赖另外一些数据计算而来的结果
语法:
computed: { "计算属性名" () { return "值" } }
需求:
需求: 求2个数的和显示到页面上
{{ num }}
注意: 计算属性也是vue数据变量, 所以不要和data里重名, 用法和data相同
总结: 一个数据, 依赖另外一些数据计算而来的结果
目标: 计算属性是基于它们的依赖项的值结果进行缓存的,只要依赖的变量不变, 都直接从缓存取结果
{{ reverseMessage }}
{{ reverseMessage }}
{{ reverseMessage }}
{{ getMessage() }}
{{ getMessage() }}
{{ getMessage() }}
总结: 计算属性根据依赖变量结果缓存, 依赖变化重新计算结果存入缓存, 比普通方法性能更高
目标: 计算属性也是变量, 如果想要直接赋值, 需要使用完整写法
语法:
computed: {
"属性名": {
set(值){
},
get() {
return "值"
}
}
}
需求:
计算属性给v-model使用
页面准备输入框
姓名:
总结: 想要给计算属性赋值, 需要使用set方法
目标: 基于之前的案例, 完成总价和均价的计算效果
此处只修改了变化的代码
统计:
总价钱为: {{ allPrice }}
平均价: {{ svgPrice }}
总结: 总价来源于所有数据计算而来的结果, 故采用计算属性
全选:
-
{{ obj.name }}
目标: 可以侦听data/computed属性值改变
语法:
watch: {
"被侦听的属性名" (newVal, oldVal){
}
}
完整例子代码:
总结: 想要侦听一个属性变化, 可使用侦听属性watch
目标: 侦听复杂类型, 或者立即执行侦听函数
语法:
watch: {
"要侦听的属性名": {
immediate: true, // 立即执行
deep: true, // 深度侦听复杂类型内变化
handler (newVal, oldVal) {
}
}
}
完整例子代码:
总结: immediate立即侦听, deep深度侦听, handler固定方法触发
目标: 侦听list变化, 同步到浏览器本地
需求: 把品牌管理的数据实时同步到本地缓存
分析:
① 在watch侦听list变化的时候, 把最新的数组list转成JSON字符串存入到localStorage本地
② data里默认把list变量从本地取值, 如果取不到给个默认的空数组
效果:
新增/删除 – 刷新页面 – 数据还在
组件是可复用的 Vue 实例, 封装标签, 样式和JS代码
组件化 :封装的思想,把页面上 可重用的部分
封装为 组件
,从而方便项目的 开发 和 维护
一个页面, 可以拆分成一个个组件,一个组件就是一个整体, 每个组件可以有自己独立的 结构 样式 和 行为(html, css和js)
口诀: 哪部分标签复用, 就把哪部分封装到组件内
(重要): 组件内template只能有一个根标签
(重要): 组件内data必须是一个函数, 独立作用域
步骤:
封装标签+样式+js - 组件都是独立的, 为了复用
芙蓉楼送辛渐
{{ isShow ? "收起" : "展开" }}
寒雨连江夜入吴,
平明送客楚山孤。
洛阳亲友如相问,
一片冰心在玉壶。
全局 - 注册使用
全局入口在main.js, 在new Vue之上注册
语法:
import Vue from 'vue'
import 组件对象 from 'vue文件路径'
Vue.component("组件名", 组件对象)
main.js
// 目标: 全局注册 (一处定义到处使用)
// 1. 创建组件 - 文件名.vue
// 2. 引入组件
import Pannel from './components/Pannel'
// 3. 全局 - 注册组件
/*
语法:
Vue.component("组件名", 组件对象)
*/
Vue.component("PannelG", Pannel)
全局注册PannelG组件名后, 就可以当做标签在任意Vue文件中template里用
单双标签都可以或者小写加-形式, 运行后, 会把这个自定义标签当做组件解析, 使用组件里封装的标签替换到这个位置
局部 - 注册使用
语法:
import 组件对象 from 'vue文件路径'
export default {
components: {
"组件名": 组件对象
}
}
任意vue文件中中引入, 注册, 使用
案例:折叠面板
(1)(创建)封装html+css+vue到独立的.vue文件中
(2)(引入注册)组件文件 => 得到组件配置对象
(3)(使用)当前页面当做标签使用
目的: 解决多个组件样式名相同, 冲突问题
需求: div标签名选择器, 设置背景色
问题: 发现组件里的div和外面的div都生效了
解决: 给Pannel.vue组件里style标签上加scoped属性即可
在style上加入scoped属性, 就会在此组件的标签上加上一个随机生成的data-v开头的属性
而且必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到
总结: style上加scoped, 组件内的样式只在当前vue组件生效
因为每个组件的变量和值都是独立的
组件通信先暂时关注父传子, 子传父
父: 使用其他组件的vue文件
子: 被引入的组件(嵌入)
例如: App.vue(父) MyProduct.vue(子)
目的: 从外面给组件内传值
步骤:
(1)创建组件components(父)/MyProduct.vue (子)
(2)子组件内在props定义变量, 用于接收外部传入的值
(3)父组件中引入注册组件, 使用时, 传入具体数据给组件显示
components/MyProduct.vue - 准备标签(子组件内, 定义变量, 准备接收, 然后使用变量)
标题: {{ title }}
价格: {{ price }}元
{{ intro }}
App.vue中使用并传入数据(引入组件, 注册组件, 使用组件, 传值进去)
总结: 组件封装复用的标签和样式, 而具体数据要靠外面传入
目的: 把数据循环分别传入给组件内显示
数据
list: [
{ id: 1, proname: "超级好吃的棒棒糖", proprice: 18.8, info: '开业大酬宾, 全场8折' },
{ id: 2, proname: "超级好吃的大鸡腿", proprice: 34.2, info: '好吃不腻, 快来买啊' },
{ id: 3, proname: "超级无敌的冰激凌", proprice: 14.2, info: '炎热的夏天, 来个冰激凌了' },
],
从父到子的数据流向,叫单向数据流
在vue中需要遵循单向数据流原则
父组件的数据发生了改变,子组件会自动跟着变
子组件不能直接修改父组件传递过来的props, props变量本身是只读不能重新赋值
注意:
父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,
对象是引用类型, 互相更新
原因: 子组件修改, 不通知父级, 造成数据不一致性
第一个MyProduct.vue内自己修改商品价格为5.5, 但是App.vue里原来还记着18.8 - 数据 不一致了
总结: props变量本身是不能重新赋值的
目标: 从子组件把值传出来给外面使用
语法:
父: @自定义事件名="父methods函数"
子: this.$emit("自定义事件名", 传值) - 执行父methods里函数代码
App.vue
components/MyProduct_sub.vue
标题: {{ title }}
价格: {{ price }}元
{{ intro }}
总结: 父自定义事件和方法, 等待子组件触发事件给方法传值
目标: 常用于跨组件通信时使用
两个没有任何引入关系的组件, 要如何互相通信呢?
两个组件的关系非常的复杂,通过父子组件通讯是非常麻烦的。
这时候可以使用通用的组件通讯方案:事件总线(event-bus)
总结: 空的Vue对象, 只负责$on注册事件, $emit触发事件, 一定要确保$on先执行
一组件从 创建 到 销毁 的整个过程就是生命周期
Vue_生命周期
目标: Vue 框架内置函数,随着组件的生命周期阶段,自动执行
作用: 特定的时间点,执行特定的操作
场景: 组件创建完毕后,可以在created 生命周期函数中发起Ajax 请求,从而初始化 data 数据
分类: 4大阶段8个方法
初始化
挂载
更新
销毁
阶段 | 方法名 | 方法名 |
---|---|---|
初始化 | beforeCreate | created |
挂载 | beforeMount | mounted |
更新 | beforeUpdate | updated |
销毁 | beforeDestroy | destroyed |
官网文档https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA
下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
目标: 掌握初始化阶段2个钩子函数作用和执行时机
含义讲解:
1.new Vue() – Vue实例化(组件也是一个小的Vue实例)
2.Init Events & Lifecycle – 初始化事件和生命周期函数
3.beforeCreate – 生命周期钩子函数被执行
4.Init injections&reactivity – Vue内部添加data和methods等
5.created – 生命周期钩子函数被执行, 实例创建
6.接下来是编译模板阶段 –开始分析
7.Has el option? – 是否有el选项 – 检查要挂到哪里
没有. 调用$mount()方法
有, 继续检查template选项
components/Life.vue - 创建一个文件
App.vue - 引入使用
1. 生命周期
目标: 掌握挂载阶段2个钩子函数作用和执行时机
含义讲解:
1.template选项检查
有 - 编译template返回render渲染函数
无 – 编译el选项对应标签作为template(要渲染的模板)
2.虚拟DOM挂载成真实DOM之前
3.beforeMount – 生命周期钩子函数被执行
4.Create … – 把虚拟DOM和渲染的数据一并挂到真实DOM上
5.真实DOM挂载完毕
6.mounted – 生命周期钩子函数被执行
学习生命周期 - 看控制台打印
{{ msg }}
目标: 掌握更新阶段2个钩子函数作用和执行时机
含义讲解:
1.当data里数据改变, 更新DOM之前
2.beforeUpdate – 生命周期钩子函数被执行
3.Virtual DOM…… – 虚拟DOM重新渲染, 打补丁到真实DOM
4.updated – 生命周期钩子函数被执行
5.当有data数据改变 – 重复这个循环
components/Life.vue - 创建一个文件
准备ul+li循环, 按钮添加元素, 触发data改变->导致更新周期开始
学习生命周期 - 看控制台打印
{{ msg }}
-
{{ val }}
目标: 掌握销毁阶段2个钩子函数作用和执行时机
含义讲解:
1.当$destroy()被调用 – 比如组件DOM被移除(例v-if)
2.beforeDestroy – 生命周期钩子函数被执行
3.拆卸数据监视器、子组件和事件侦听器
4.实例销毁后, 最后触发一个钩子函数
5.destroyed – 生命周期钩子函数被执行
components/Life.vue - 准备生命周期方法(Life组件即将要被删除)
主要: App.vue - 点击按钮让Life组件从DOM上移除 -> 导致Life组件进入销毁阶段
目标: 利用 ref 和 $refs 可以用于获取 dom 元素
components/More.vue
1. 获取原生DOM元素
我是一个孤独可怜又能吃的h1
总结: 通过id / ref, 都可以获取原生DOM标签
目标: 获取组件对象, 调用组件里方法
components/Child/Demo.vue
我是Demo组件
More.vue - 获取组件对象 - 调用组件方法
1. 获取原生DOM元素
我是一个孤独可怜又能吃的h1
2. 获取组件对象 - 可调用组件内一切
总结: ref定义值, 通过$refs.值 来获取组件对象, 就能继续调用组件内的变量
Vue更新DOM-异步的
目标: 点击count++, 马上通过"原生DOM"拿标签内容, 无法拿到新值
components/Move.vue - 继续新增第三套代码
1. 获取原生DOM元素
我是一个孤独可怜又能吃的h1
2. 获取组件对象 - 可调用组件内一切
3. vue更新DOM是异步的
{{ count }}
总结: 因为DOM更新是异步的
目标: 点击搜索按钮, 弹出聚焦的输入框, 按钮消失
目标: 可以用组件的name属性值, 来注册组件名字
问题: 组件名不是可以随便写的?
答案: 我们封装的组件-可以自己定义name属性组件名-让使用者有个统一的前缀风格
components/Com.vue
我是一个Com组件
App.vue - 注册和使用
1. 生命周期
2. axios使用
3. $refs的使用
4. $nextTick使用场景
5. 组件对象里name属性