更少的时间,更多的活。开发网站速度快。
把数组数据-循环铺设到li中, 看看分别如何做的?
1、原生js做法
2、Vue.js做法
{{item}}
(vue的底层还是原生js)
开发更加的效率和简洁, 易于维护, 快!快!快!就是块 (甚至测试, Java, Python工程师都要学点vue, 方便与前端沟通)
现在很多项目都是用vue开发的
市场上90%工作都要求会vue, 会vue拿高薪, 甚至java或测试都要学点vue
为什么学 Vue
1、开发更快,更高效
2、企业开发都在使用
3、前端工程师必备技能,高薪
logo镇楼
渐进式javacript框架, 一套拥有自己规则的语法
官网地址: Vue.js - 渐进式 JavaScript 框架 | Vue.js (作者: 尤雨溪)
尤雨溪:大学专业并非是计算机专业,在大学期间他学习专业是室内艺术和艺术史,后来读了美术设计和技术的硕士,正是在读硕士期间,他偶然接触到了JavaScript ,从此被这门编程语言深深吸引,开启了自己的前端生涯。
2014 年 2 月,Vue.js 正式发布
2015 年 10 月 27 日,正式版发布 1.0.0
2016 年 4 月 27 日,发布 2.0 的预览版本
渐进式: 逐渐进步, 想用什么就用什么, 不必全都使用
逐渐使用,逐渐进步
简单来说:一辆车(轮子+发动机)-> 方向盘 -> 车灯 -> 翅膀 = 能飞的汽车
Vue渐进式: Vue从基础开始, 会循序渐进向前学习, 如下知识点可能你现在不明白, 但是学完整个vue回过头来看, 会很有帮助
声明式渲染 -> 组件系统 -> 客户端路由 -> 大规模状态管理 -> 构建工具
补充概念:
库: 封装的属性或方法 (例jquery.js)
框架: 拥有自己的规则和元素, 比库强大的多 (例vue.js)
第一列:某个知识点
第二列:语法示列
第三列:当前知识点的详细介绍
第四列:当前知识点的应用场景
例子、项目,没有标准答案,以完成功能为导向。
实现功能,不是最终目的。同样一个功能,自己思考,还有没有其他的写法,其他的实现思路。
遇到报错,先翻译。翻译完了再根据报错内容,查找bug
vue是渐进式框架, 有自己的规则, 我们要记住语法, 特点和作用, 反复磨炼使用, 多总结
在哪里书写 Vue 代码呢?
在工程化环境下用 Vue 开发项目。
1、新的开发模式是不是离不开 webpack?
2、自己配置 webpack 是不是非常痛苦?
3、有没有一套搭建好的,拿来即用的环境呢?
webpack自己配置环境很麻烦, 下载@vue/cli包,用vue命令创建脚手架项目
开箱即用
0配置webpack
babel支持
css, less支持
开发服务器支持
需要自己配置 webpack 吗?
Vue 官方提供了@vue/cli 包 - 可以创建脚手架项目
脚手架的好处
0 配置开箱即用,基于它开发我们的项目
有了 vue 命令,如何创建一套脚手架项目?
把@vue/cli模块包按到全局, 电脑拥有vue命令, 才能创建脚手架工程
1、全局安装命令
yarn global add @vue/cli
# OR
npm install -g @vue/cli
注意: 如果半天没动静(95%都是网速问题), 可以ctrl+c:停止重新来、换一个网继续重来
2、查看vue
脚手架版本
vue -V
1、如何安装全局包?
yarn global add 包名 / npm install 包名 -g
2、我们得到什么?
全局包会在计算机中配置全局命令(例:vue 命令)
有了 vue 命令,如何创建一套脚手架项目?
使用vue命令, 创建脚手架项目
注意: 项目名不能带大写字母, 中文和特殊符号
# vue和create是命令, vuecli-demo是文件夹名
vue create vuecli-demo
选择用什么方式下载脚手架项目需要的依赖包
cd vuecil-demo
npm run serve
# 或
yarn serve
只要看到绿色的 - 啊. 你成功了(底层node+webpack热更新服务)
打开浏览器输入上述地址
vue命令创建工程目录, 项目内置webpack本地热更新服务器, 帮我们打包项目预览项目
1、如何创建一个开箱即用的脚手架项目
vue create 项目名
2、如何在网页浏览这个项目
yarn serve 启动本地热更新开发服务器
讲解重点文件夹, 文件的作用, 以及文件里代码的意思
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 – 依赖包列表文件
项目入口和个文件关系是什么呢?
知道项目入口, 以及代码执行顺序和引入关系
main.js、App.vue 和 index.html 作用和关系?
1、main.js - 项目打包入口 - Vue 初始化
2、App.vue - Vue 页面主入口
3、index.html - 浏览器运行的文件
4、App.vue => main.js => index.html
项目中没有webpack.config.js文件,因为@vue/cli用的vue.config.js
src并列处新建vue.config.js
/* 覆盖webpack的配置 */
module.exports = {
devServer: { // 自定义服务配置
open: true, // 自动打开浏览器
port: 3000
}
}
脚手架项目配置文件
src 文件夹并列处准备 vue.config.js 配置文件
知道eslint的作用, 和如何暂时关闭, 它是一个代码检查工具
先在main.js 随便声明个变量, 但是不要使用
观察发现, 终端和页面都报错了
记住以后见到这样子的错误, 证明你的代码不严谨
方式1: 手动解决掉错误, 以后项目中会讲如何自动解决
方式2: 暂时关闭eslint检查(因为现在主要精力在学习Vue语法上), 在vue.config.js中配置后重启服务
1、eslint 是什么?
eslint 是代码检查工具,违反规定就报错
2、如何关闭?
在 vue.config.js 中设置 lintOnSave 为 false 重启服务器即可
单vue文件好处, 独立作用域互不影响
Vue推荐采用.vue文件来开发项目
template里只能有一个根标签
vue文件-独立模块-作用域互不影响
style配合scoped属性, 保证样式只针对当前template内标签生效
vue文件配合webpack, 把他们打包起来插入到index.html
欢迎使用vue
最终: Vue文件配合webpack, 把他们打包起来插入到index.html, 然后在浏览器运行
单 vue 文件好处
独立作用域,不再担心变量问题。
单文件使用注意事项
要注意 template 里只能有一个根标签
我们开始写我们自己的代码, 无需欢迎页面
src/App.vue默认有很多内容, 可以全部删除留下框
assets 和 components 文件夹下的一切都删除掉 (不要默认的欢迎页面)
1、以前改变标签内容,如何做?
2、用 Vue 有没有更简单的方式?
在dom标签中, 直接插入内容
又叫: 声明式渲染/文本插值
语法: {{ 表达式 }}
{{ msg }}
{{ obj.name }}
{{ obj.age > 18 ? '成年' : '未成年' }}
什么是插值表达式
双大括号,可以把 vue 数据变量显示在标签内
Vue 中变量声明在哪里
data 函数返回的对象上,用 key 属性声明
在上个代码基础上,在 devtool 工具改变 M 层的变量,观察 V 层(视图的自动同步)
为什么数据改变页面自动更新了?
转变思维,用数据驱动视图改变,操作dom的事, vue源码内干了
是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
数据双向绑定
让数据自动地双向同步 不再需要操作DOM1. 在vue中,不推荐直接手动操作DOM!!!
2. 在vue中,通过数据驱动视图,不要在想着怎么操作DOM,而是想着如何操作数据!!(思想转变)
vue源码内采用MVVM设计模式思想, 大大减少了DOM操作, 挺高开发效率
1、什么是设计模式
设计模式适度代码分层,引入一种架构的概念
2、MVVM 是什么?
MVVM(模型、视图、视图模型双向关联的一种设计模式)
3、MVVM 的好处?
减少 DOM 操作,提高开发效率
以前给 a 标签设置 href 如何做呢?
给标签属性设置vue变量的值
插值表达式不能用在html的属性上,如果想要动态的设置html元素的属性,需要使用v-bind指令
vue指令, 实质上就是特殊的 html 标签属性, 特点: v- 开头
每个指令, 都有独立的作用
v-bind:属性名="vue变量"
:属性名="vue变量"
我是a标签
把vue变量的值, 赋予给dom属性上, 影响标签显示效果
如何给 dom 标签的属性,设置 Vue 数据变量?
:属性名="vue 数据变量"
以前如何给按钮绑定点击事件呢?
给标签绑定事件
你要买商品的数量: {{count}}
1、如何给 dom 标签绑定事件?
@事件名=“methods 里的函数名”
2、如何给事件传值呢?
@事件名=“methods 里的函数名(实参)”
1、js 原生如何阻止标签的默认行为?
2、vue 事件处理函数如何获取事件对象呢?
vue事件处理函数中, 拿到事件对象
无传参, 通过形参直接接收
传参, 通过$event指代事件对象传给事件处理函数
Vue 事件处理函数,如何拿到事件对象呢?
1、无传参,直接在形参接收
2、有传参,手动传入$event 对象
1、e.preventDefault()单词很长不好写吧?
2、有没有一种更简单的方式实现呢?
在事件后面.修饰符名 - 给事件带来更强大的功能
@事件名.修饰符="methods里函数"
修饰符给事件扩展额外功能
vue 有哪些主要修饰符,都有什么功能?
1、.stop - 阻止事件冒泡
2、.prevent - 阻止默认行为
3、.once - 只执行一次事件处理函数
1、以前我想判断用户是否按下回车怎么做?
2、鼠标事件有修饰符,那按键有修饰符吗?
给键盘事件, 添加修饰符, 增强能力
更多修饰符
多使用事件修饰符, 可以提高开发效率, 少去自己判断过程
1、按键修饰符如何用?
@键盘事件.按键修饰符=“methods 里函数名”
2、有哪些主要按键修饰符?
1、.enter - 只要按下回车才能触发这个键盘事件函数
2、.esc - 只要按下取消键才能触发这个键盘事件函数
点击按钮 - 把文字取反显示 - 再点击取反显示(回来了)
提示把字符串取反赋予回去
效果演示:
1、如何反转字符串?
2、视图如何实时更新?
1、定义变量 message:‘HELLO, WORLD’
2、插值表达式赋予到dom上, 准备按钮和文字
3、按钮绑定点击事件和函数
4、对message值用split拆分, 返回数组
5、数组元素翻转用reverse方法
6、再把数组用join拼接成字符串赋予给message
7、因为Vue是MVVM设计模式, 数据驱动视图, 所以视图自动改变
正确代码:
{{ message }}
记住方法特点, 多做需求, vue是数据变化视图自动更新, 减少操作DOM时间, 提高开发效率
点击翻转字符串你有什么收获?
1、写需求要先静态标签, 再考虑动态效果, 找好第一步干什么
2、记住方法的特点 – 可以自己总结字典和口诀
3、Vue是靠数据驱动视图, 只需要关心数据变化即可
1、js中获取表单的值, 赋予给变量?
2、js变量改变, 同步显示到表单里?
3、Vue能否把他们互相关联起来呢?
把value属性和vue数据变量, 双向绑定到一起
用户名:
密码:
来自于:
爱好:
抽烟
喝酒
写代码
性别:
男
女
自我介绍
本阶段v-model只能用在表单元素上, 以后学组件后讲v-model高级用法
1、v-model用在哪里?
暂时只能用在表单标签上
2、v-model有什么作用?
把vue的数据变量和表单的value属性双向绑定在一起
实现原理:
代码:
export default {
data() {
return {
msg: '',
};
},
};
1、下拉菜单, 复选框, 单选框如何绑定Vue变量呢?
1、下拉菜单v-model写在哪里?
在select, value在option上
2、v-model用在复选框时, 需要注意什么?
v-model的vue变量是
非数组 – 关联的是checked属性
数组 – 关联的是value属性
3、vue变量初始值会不会影响表单的默认状态?
会影响, 因为双向数据绑定-互相影响
1、表单同步到变量里的 数 是什么类型的呢?
2、能否让v-model转成数值再赋予给变量呢?
让v-model拥有更强大的功能
v-model.修饰符="vue数据变量"
年龄:
人生格言:
自我介绍:
v-model修饰符, 可以对值进行预处理, 非常高效好用
v-model有哪些修饰符, 提高我们编程效率?
1、.number – 转成数值类型赋予给Vue数据变量
2、.trim – 去除左右两边空格后把值赋予给Vue数据变量
3、.lazy – 等表单失去焦点, 才把值赋予给Vue数据变量
更新DOM对象的innerText/innerHTML
v-text把值当成普通字符串显示, v-html把值当做html解析
1、v-text和v-html有什么作用?
都可以设置标签显示的内容
2、区别是什么?
v-text把值当成普通字符串显示
v-html把值当成标签进行解析显示
控制标签的隐藏或出现
v-show的盒子
v-if的盒子
我成年了
还得多吃饭
使用v-show和v-if以及v-else指令, 方便通过变量控制一套标签出现/隐藏
点击展开或收起时,把内容区域显示或者隐藏
此案例使用了less语法, 项目中下载模块
yarn add [email protected] [email protected] -D
只有标签和样式
案例:折叠面板
芙蓉楼送辛渐
收起
寒雨连江夜入吴,
平明送客楚山孤。
洛阳亲友如相问,
一片冰心在玉壶。
正确答案:
案例:折叠面板
芙蓉楼送辛渐
{{ isShow ? '收起' : '展开' }}
寒雨连江夜入吴,
平明送客楚山孤。
洛阳亲友如相问,
一片冰心在玉壶。
列表渲染, 所在标签结构, 按照数据数量, 循环生成
注意
v-for的临时变量名不能用到v-for范围外
学生姓名
-
{{ index }} - {{ item }}
学生详细信息
-
{{ obj.name }}
{{ obj.sex }}
{{ obj.hobby }}
老师信息
{{ key }} -- {{ value }}
序号
{{ i }}
vue最常用指令, 铺设页面利器, 快速把数据赋予到相同的dom结构上循环生成
当v-for遍历的目标结构改变, Vue触发v-for的更新
情况1: 数组翻转
情况2: 数组截取
情况3: 更新值
数组变更方法, 就会导致v-for更新, 页面更新
数组非变更方法, 返回新数组, 就不会导致v-for更新, 可采用覆盖数组或this.$set()
-
{{ val }}
这些方法会触发数组改变, v-for会监测到并更新页面
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
这些方法不会触发v-for更新
slice()
filter()
concat()
注意: vue不能监测到数组里赋值的动作而更新, 如果需要请使用Vue.set() 或者this.$set(), 或者覆盖整个数组
改变原数组的方法才能让v-for更新
v-for
的默认行为会尝试原地修改元素而不是移动它们。
详解v-for就地更新流程(可以看ppt动画)
这种 虚拟DOM对比方式, 可以提高性能 - 但是还不够高
了解虚拟DOM的概念
.vue文件中的template里写的标签, 都是模板, 都要被vue处理成虚拟DOM对象, 才会渲染显示到真实DOM页面上
123
对应的虚拟DOM结构
好处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: 根元素没变, 子元素没变, 元素内容改变
v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM, 你需要用特殊 attribute key
来提供一个排序提示
-
{{ str }}
export default {
data(){
return {
arr: ["老大", "新来的", "老二", "老三"]
}
},
methods: {
addFn(){
this.arr.splice(1, 0, '新来的')
}
}
};
旧 - 虚拟DOM结构 和 新 - 虚拟DOM结构 对比过程
性能不高, 从第二个li往后都更新了
因为新旧虚拟DOM对比, key存在就复用此标签更新内容, 如果不存在就直接建立一个新的
-
{{ str }}
export default {
data(){
return {
arr: ["老大", "新来的", "老二", "老三"]
}
},
methods: {
addFn(){
this.arr.splice(1, 0, '新来的')
}
}
};
key为索引-图解过程 (又就地往后更新了)
key的值只能是唯一不重复的, 字符串或数值
v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM, 你需要用特殊 attribute key
来提供一个排序提示
新DOM里数据的key存在, 去旧的虚拟DOM结构里找到key标记的标签, 复用标签
新DOM里数据的key存在, 去旧的虚拟DOM结构里没有找到key标签的标签, 创建
旧DOM结构的key, 在新的DOM结构里没有了, 则移除key所在的标签
-
{{ obj.name }}
总结: 不用key也不影响功能(就地更新), 添加key可以提高更新的性能
1、JS 判断标签是否应该使用某个类名?
2、vue 能不能直接在标签里判断?
用v-bind给标签class设置动态的值
:class="{类名: 布尔值}"
-
{{ item.name }}
如何给标签 class 属性动态赋值?
:class=“{类名: 布尔值}”, true 使用, false 不用
class=“{类名 1:布尔值 1,class2:布尔值 2}”
多个 class,用“,”逗号隔开
动态class
动态class
class 与 :class 可以并存
data() {
return{
activeClass: 'active',
errorClass: 'text-danger'
}
}
呈现出来的效果:
好好学习
data() {
return {
bool: false,
};
},
};
:style="{css属性: 值}"
注意:
1.如果css样式是需要短横线的,需要将短横线删除使用小驼峰命名法
好好学习天天向上
2.css属性值需要加引号可以直接引用数值,可以不用设置变量
好好学习天天向上
动态style也有动态style对象语法,动态style数组语法,动态style三元运算语法
好好学习天天向上
吃饭了吗
一会去吃饭
你好吗,三元运算
数据铺设
① 先铺设静态页面 --- 去.md文档里, 复制数据和标签模板
② 此案例使用bootstrap, 需要下载, 并导入到工程main.js中
③ 用v-for配合默认数据, 把数据默认铺设到表格上显示
④ 直接在标签上, 大于100价格, 动态设置red类名
yarn add bootstrap
2.在main.js - 引入bootstrap
import "bootstrap/dist/css/bootstrap.css" // 默认找文件夹下的index文件(但是这个不是所以需要写路径)
3正确代码
品牌管理
编号
资产名称
价格
创建时间
操作
{{ item.id }}
{{ item.name }}
{{ item.price }}
{{ item.time }}
删除
1、布局用 bootstrap, yarn 下载引入使用
2、v-for 把数据渲染到表格里
3、:class 动态判断价格给红色类名
数据新增
① 添加资产按钮 – 绑定点击事件
② 给表单v-model绑定vue变量收集用户输入内容
③ 添加数据到数组中
④ 判断用户内容是否符合规定
在上个案例代码基础上接着写
品牌管理
编号
资产名称
价格
创建时间
操作
{{ item.id }}
{{ item.name }}
{{ item.price }}
{{ item.time }}
删除
1、@绑定事件
2、v-model 收集表单数据
3、.prevent 阻止按钮提交表单刷新页面
4、v-model 修饰符
5、数组取最后一个元素
数据删除
① a标签绑定点击事件
② 给事件方法传id
③ 通过id, 找到对应数据删除
④ 删除光了要让tfoot显示
⑤ 删除光了再新增, 有bug(id值问题)需要修复
在上个案例代码基础上接着写
删除
涉及到了哪些技术点?
1、事件传 id
2、删除数组元素方法
3、id 值判断问题
复制上个案例, 在此基础上, 把表格里的时间用过滤器+moment模块, 格式化成YYYY-MM-DD 格式
yarn add moment
// 目标: 处理时间
// 1. 下载moment模块
import moment from 'moment'
// 2. 定义过滤器, 编写内部代码
filters: {
formatDate (val){
return moment(val).format('YYYY-MM-DD')
}
}
{{ obj.time | formatDate }}
品牌管理
编号
资产名称
价格
创建时间
操作
{{ item.id }}
{{ item.name }}
{{ item.price }}
{{ item.time | time }}
删除
总资产{{ allPrice }}
平均资产{{ junPrices }}
暂无数据
总价来源于所有数据计算而来的结果, 故采用计算属性
涉及到的知识点
1、computed 定义和使用计算属性
2、数组 reduce 方法累积运算
1、JS 原生如何封装一个字母翻转的函数?
2、生活当中的过滤器是什么? Vue 中如何实现过滤器?
转换格式, 过滤器就是一个函数, 传入值返回处理后的值
1、过滤器只能用在, 插值表达式和v-bind表达式
2、Vue中的过滤器场景
Vue.filter('reverse', (val, s) => {
return val.split('').reverse().join(s);
});
filters: {过滤器名字: (值) => {return "返回处理后的值"}
filters: {
reverse(val) {
return val.split('').reverse().join(s);
},
},
原来的样子: {{ msg }}
使用翻转过滤器: {{ msg | reverse }}
鼠标长停
把值转成另一种形式, 使用过滤器, Vue3用函数替代了过滤器.
全局注册最好在main.js中注册, 一处注册到处使用
可同时使用多个过滤器, 或者给过滤器传参
原来的样子: {{ msg }}
使用翻转过滤器: {{ msg | reverse('|') }}
鼠标长停
过滤器可以传参, 还可以对某个过滤器结果, 后面在使用一个过滤器
1、多个过滤器使用?
vue 变量 | 过滤器 1 | 过滤器 2
2、如何给过滤器传额外值
vue 变量 | 过滤器(值)
一个数据, 依赖另外一些数据计算而来的结果
{{ '计算属性名' }}
computed: {
"计算属性名" () {
return "值"
}
}
需求
{{ num }}
计算属性也是vue数据变量, 所以不要和data里重名, 用法和data相同
一个数据, 依赖另外一些数据计算而来的结果
1、计算属性使用场景?
当变量的值, 需要通过别人计算而得来
2、计算属性特点?
函数内使用的变量改变, 重新计算结果返回
3、计算属性注意事项?
计算属性名和 data 里名字不能重复
计算属性是基于它们的依赖项的值结果进行缓存的,只要依赖的变量不变, 都直接从缓存取结果
{{ Message }}
{{ Message }}
{{ Message }}
{{ getMessage() }}
{{ getMessage() }}
{{ getMessage() }}
计算属性根据依赖变量结果缓存, 依赖变化重新计算结果存入缓存, 比普通方法性能更高
1、计算属性好处是?
带缓存
依赖项不变, 直接从缓存取
依赖项改变, 函数自动执行并重新缓存
2、计算属性使用场景?
当变量值, 依赖其他变量计算而得来才用
目标:计算属性也是变量
语法:
computed: {
"属性名": {
set(值){
},
get() {
return "值"
}
}
}
给关联v-model需要给计算属性变量赋值的时候需要用到计算属性完整写法
姓名:
set 接收要赋予的值
get 里要返回给这个计算属性具体值
一、小选影响全选
小选框都选中(手选), 全选自动选中
① 先静态后动态, 从.md拿到静态标签和数据
② 循环生成复选框和文字, 对象的c属性和小选框的选中状态, 用v-model双向绑定
③ 定义isAll计算属性, 值通过小选框们统计c属性状态得来
全选:
-
任务名
正确代码,不可复制
全选:
-
{{ obj.name }}
小选框如何影响全选框选中状态的?
v-model 给全选框绑定 isAll 计算属性
isAll 计算属性里返回统计小选框选中状态结果
①: isAll改成完整写法, set里获取到全选框, 勾选的状态值
②: 遍历数据数组, 赋给所有小选框v-model关联的属性
全选如何影响小选框选中状态的?
1、小选框 v-model, 关联数组里对象的 c 属性
2、isAll 计算属性的 set 方法, 拿到全选框状态
3、状态值赋给, 数组里每个对象的 c 属性
点击反选, 让所有小选框, 各自取相反勾选状态
1、小选框的勾选状态, 在对象的 c 属性
2、遍历所有对象, 把对象的 c 属性取相反值赋予回去即可
反选如何实现的?
遍历每个对象, 把 c 属性的值取反再赋予回去
侦听到name值得改变
watch:{
变量名(newVal,oldVal){
}
}
如何侦听到某个变量值改变呢?
使用 watch 配置项, key 是要侦听的 data/计算属性名
可以执行深度侦听
watch: {
user: {
handler(newVal, oldVal) {
// user里的对象
console.log(newVal, oldVal);
},
deep: true,
immediate: true,
},
},
1、如何侦听一个对象/数组呢?
把侦听器写成对象形式, 给 handler 方法和 deep:true
2.一打开网页立马执行
immediate: true
计算属性(computed) |
属性检测(watch) |
首次运行 |
首次不运行 |
调用时需要在模板中渲染,修改计算所依赖元数据 |
调用时只需修改元数据 |
默认深度依赖 |
默认浅度观测 |
1、功能:computed是计算属性;watch是监听一个值的变化执行对应的回调。
2、是否调用缓存:computed函数所依赖的属性不变的时候会调用缓存;watch每次监听的值发生变化时候都会触发。
3、是否调用return:computed必须有;watch可以没有。
4、使用场景:computed的值受多个属性影响的时候;例如购物车商品结算;watch当一条数据影响多条数据的时候,例如搜索框。
1、以前遇到重复的标签, 如何做的?
2、效率或独立性高吗, 担心变量重名?
1、以前遇到重复的标签, 如何做的?
2、效率或独立性高吗, 担心变量重名?
3、代码实现
import Pannel from './components/Pannel';
export default {
components: {
//注册组件
//'标签名': '组件名',
// Pannel: Pannel,
//当标签名和组件名一致的时候可以缩写
Pannel
},
};
引入后可以直接引用
1、遇到重复标签想复用?
封装成组件
2、组件好处?
各自独立, 便于复用
组件的概念,什么是组件?
1、组件是可复用的 Vue 实例, 封装标签, 样式和 JS 代码。
2、组件化 :封装的思想,把页面上 可重用的部分
封装为 组件
,从而方便项目的开发和维护。
3、一个页面, 可以拆分成一个个组件, 一个组件就是一个整体, 每个组件可以有自己独立的结构样式和行为(html, css 和 js)。
1、组件是什么?
可复用的 vue 实例, 封装标签, 样式, JS
2、什么时候封装组件?
遇到重复标签, 可复用的时候
3、组件好处?
各自独立, 互不影响
如何创建和使用组件?
每个组件都是一个独立的个体, 代码里体现为一个独立的.vue 文件
口诀: 哪部分标签复用, 就把哪部分封装到组件内
(重要): 组件内template只能有一个根标签
(重要): 组件内data必须是一个函数, 独立作用域
1、创建组件, 封装要复用的标签, 样式, JS 代码
2、注册组件
全局注册 – main.js 中
import Vue from 'vue';
import App from './App.vue';
import 组件对象 from 'vue文件路径';
Vue.component('组件名', 组件对象);
局部注册 – 某.vue 文件内 – 语法如图
import 组件对象 from 'vue文件路径';
export default {
components: {
PannelL: Pannel,
},
};
3、使用组件
1、创建和使用组件步骤?
创建.vue 文件,封装标签 – 样式 – JS 进去
注册组件 (全局 / 局部)
使用组件 (组件名用作标签)
2、组件运行结果?
把组件标签最终替换成, 封装的组件内标签
组件内的 scoped 是如何工作的?
解决多个组件样式名相同, 冲突问题
需求: div标签名选择器, 设置背景色
问题: 发现组件里的div和外面的div都生效了
解决: 给Pannel.vue组件里style标签上加scoped属性即可
在style上加入scoped属性, 就会在此组件的标签上加上一个随机生成的data-v开头的属性
而且必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到
重点
当前组件内标签都被添加 data-v-hash 值 的属性
div[data-v-0a305208] {
color: red;
}
css 选择器都被添加 [data-v-hash 值] 的属性选择器
1、Vue 组件内样式, 只针对当前组件内标签生效如何做?
给 style 上添加 scoped
2、原理和过程是什么?
会自动给标签添加 data-v-hash 值属性, 所有选择都 带属性选择
一、组件通信父向子
思考
1、从一个组件内, 给另外一个组件传值?
2、不使用 localStorage, 直接传递, 如何做?
目的
从外面给组件内传值, 先学会语法, 练习中在看使用场景
目标
父组件 - > 子组件 传值
首先明确父和子是谁, 在父引入子 (被引入的是子) 父: App.vue 子: MyProduct.vue 创建 MyProduct.vue
需求
封装一个商品组件MyProduct.vue - 外部传入具体要显示的数据, 如下图所示
首先渲染静态页面,勾出框架
MyProdect.vue
标题: 超级好吃的口水鸡
价格:50元
全场8折
App.vue
子组件内, 定义变量, 准备接收, 然后使用变量
标题: {{ title }}
价格: {{ price }}元
{{ intro }}
2、父组件
父组件(App.vue)内, 要展示封装的子组件(MyProduct.vue)
步骤:引入组件, 注册组件, 使用组件, 传值进去
组件封装复用的标签和样式, 而具体数据要靠外面传入
1、什么时候需要父传子技术?
从一个 vue 组件里把值传给另一个 vue 组件(父- >子)
2、父传子口诀(步骤)是什么?
子组件内, props 定义变量, 在子组件使用变量
父组件内, 使用子组件, 属性方式给 props 变量传值
1、能循环使用组件吗?
2、每次循环使用组件, 独立向组件内传值?
把数据循环分别传入给组件内显示
父组件 - > 子组件 循环使用-传值
数据
list: [
{
id: 1,
proname: "超级好吃的棒棒糖",
proprice: 18.8,
info: "开业大酬宾, 全场8折",
},
{
id: 2,
proname: "超级好吃的大鸡腿",
proprice: 34.2,
info: "好吃不腻, 快来买啊",
},
{
id: 3,
proname: "超级无敌的冰激凌",
proprice: 14.2,
info: "炎热的夏天, 来个冰激凌了",
},
],
代码
1、key 属性绑定 id
2、组件属性加冒号,因为传的是变量
循环使用组件注意事项?
每次循环, 变量和组件, 都是独立的
1、子组件内想实现砍价功能, 点一次按钮砍掉价格?
2、子组件内能改变, 父传入的数据吗?
1、子组件修改, 不通知父级, 会造成数据不一致性,子数据来源于数据
2、Vue 规定 props 里的变量, 本身是只读的,不能用来赋值
1、父组件的数据发生了改变,子组件会自动跟着变
2、子组件不能直接修改父组件传递过来的props props是只读的
1、为何不建议, 子组件修改父组件传过来的值?
父子数据不一致, 而且子组件是依赖父传入的值
2、什么是单向数据流?
从父到子的数据流向, 叫单向数据流
3、props 里定义的变量能修改吗?
不能, props 里的变量本身是只读的
那子组件如何才能修改父组件里的数据呢?
课上例子, 砍价功能, 子组件点击实现随机砍价功能
标题: {{ title }}
价格: {{ price }}元
{{ info }}
因为单向数据流问题,会导致报错
子组件触发父自定义事件方法
父: @自定义事件名="父methods函数"
子: this.$emit("自定义事件名", 传值) - 执行父methods里函数代码
绑定自定义事件和事件处理函数
export default {
methods: {
fn('参数'){
// 逻辑代码
}
}
};
2、子组件
恰当的时机, 触发父组件自定义事件, 导致父 methods 里事件处理函数执行
export default {
methods: {
subFn() {
//this.$emit('自定义事件名', 值);
this.$emit('subprice', '值'); // 子向父
},
},
};
1、什么时候使用子传父技术?
当子想要去改变父里的数据
2、子传父如何实现?
父组件内, 给组件@自定义事件="父 methods 函数" 子组件内, 恰当时机
this.$emit('自定义事件名', 值);
传值后可以相互影响相互改变
两个没有任何引入关系的组件, 要如何互相通信呢?
EventBus
常用于跨组件通信时使用
两个组件的关系非常的复杂,通过父子组件通讯是非常麻烦的。这时候可以使用通用的组件通讯方案:事件总线(event-bus)
1、src/EventBus/index.js – 创建空白 Vue 对象并导出
2、在要接收值的组件(List.vue) eventBus.$on('事件名', 函数体)
3、在要传递值的组件(MyProduct.vue) eventBus.$emit('事件名', 值)
EventBus/index.js- 定义事件总线bus对象
import Vue from 'vue'
// 导出空白vue对象
export default new Vue()
List.vue注册事件 - 等待接收要砍价的值 (直接复制) - 准备兄弟页面
-
{{ item.proname }}
{{ item.proprice }}
List.vue正确代码(EventBus接收方)
-
{{ item.proname }}
{{ item.proprice }}
1、什么时候使用 eventBus 技术?
当 2 个没有引用关系的组件之间要通信传值
2、eventBus 技术本质是什么?
空白 Vue 对象, 只负责emit
1、子父组件通信
2、事件总线(EventBus)(适合小型项目:页面少、功能少)
3、依赖注入(不推荐使用)(数据流向不好追溯)
4、vuex(企业级项目常用)
5、浏览器缓存
6、etc。。。。
1、什么是生命周期?
2、Vue所谓的生命周期又是什么?
一组件从 创建 到 销毁 的整个过程就是生命周期
Vue_生命周期
Vue 框架内置函数,随着组件的生命周期阶段,自动执行
特定的时间点,执行特定的操作
组件创建完毕后,可以在created 生命周期函数中发起Ajax 请求,从而初始化 data 数据
4大阶段8个方法
阶段 |
方法名 |
方法名 |
初始化 |
beforeCreate |
created |
挂载 |
beforeMount |
mounted |
更新 |
beforeUpdate |
updated |
销毁 |
beforeDestroy |
destroyed |
官网文档
下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
1、如何知道Vue生命周期到达了什么阶段?
使用钩子函数
2、钩子函数有哪些?
初始化 / 挂载 / 更新 / 销毁
掌握初始化阶段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. 生命周期
1、Vue实例从创建到编译模板执行了哪些钩子函数?
beforeCreate / created
2、created函数触发能获取data?
能获取data, 不能获取真实DOM
1、我们在template里写的是真实的DOM吗?
2、哪个钩子函数里能获取真实DOM呢?
掌握挂载阶段2个钩子函数作用和执行时机
1.template选项检查
有 - 编译template返回render渲染函数
无 – 编译el选项对应标签作为template(要渲染的模板)
2.虚拟DOM挂载成真实DOM之前
3.beforeMount – 生命周期钩子函数被执行
4.Create … – 把虚拟DOM和渲染的数据一并挂到真实DOM上
5.真实DOM挂载完毕
6.mounted – 生命周期钩子函数被执行
components/Life.vue - 创建一个文件
学习生命周期 - 看控制台打印
{{ msg }}
1、Vue实例从创建到显示都经历了哪些钩子函数?
beforeCreate / created / beforeMount / mounted
2、created函数里, 能获取真实DOM吗?
不能获取真实DOM
3、在什么钩子函数里可以获取真实DOM?
mounted
data数据改变会触发哪些钩子函数呢?
掌握更新阶段2个钩子函数作用和执行时机
1.当data里数据改变, 更新DOM之前
2.beforeUpdate – 生命周期钩子函数被执行
3.Virtual DOM…… – 虚拟DOM重新渲染, 打补丁到真实DOM
4.updated – 生命周期钩子函数被执行
5.当有data数据改变 – 重复这个循环
components/Life.vue - 创建一个文件
准备ul+li循环, 按钮添加元素, 触发data改变->导致更新周期开始
1、什么时候执行updated钩子函数
当数据发生变化并更新页面后
2、在哪可以获取更新后的DOM
在updated钩子函数里
掌握销毁阶段2个钩子函数作用和执行时机
1.当$destroy()被调用 – 比如组件DOM被移除(例v-if)
2.beforeDestroy – 生命周期钩子函数被执行
3.拆卸数据监视器、子组件和事件侦听器
4.实例销毁后, 最后触发一个钩子函数
5.destroyed – 生命周期钩子函数被执行
components/Life.vue - 准备生命周期方法(Life组件即将要被删除)
主要: App.vue - 点击按钮让Life组件从DOM上移除 -> 导致Life组件进入销毁阶段
一般在beforeDestroy/destroyed里做什么?
手动消除计时器/定时器/全局事件
1、Vue中如何获取真实DOM元素?
2、还有没有更多方式?
通过id或ref属性获取原生DOM
在mounted生命周期 – 2种方式获取原生DOM标签
1、目标标签 – 添加id / ref
2、恰当时机, 通过id / 通过ref属性 获取目标标签
获取原生dom
mounted(){ //mounted 生命周期内部
console.log(document.getElementById("h")); // h1
console.log(this.$refs.myH); // h1
},
Vue中如何获取原生DOM呢?
用id属性或者ref属性都可以
Vue中能否获取组件对象呢?
通过ref属性获取组件对象
1、创建Demo组件, 写一个方法
2、App.vue使用Demo组件, 给ref属性-名字随意
3、恰当时机, 通过ref属性 获取组件对象, 可调用组件对象里方法等
components/Child/Demo.vue
我是Demo组件
More.vue - 获取组件对象 - 调用组件方法
1. 获取原生DOM元素
我是一个孤独可怜又能吃的h1
2. 获取组件对象 - 可调用组件内一切
1、如何获取组件对象呢?
目标组件添加ref属性
this.$refs.名字 获取组件对象
2、拿到组件对象能做什么?
调用组件里的属性/方法
data数据改变, 马上获取DOM里的内容如何写?
目标:点击改data,获取原生DOM内容
1、创建标签显示数据
2、点击+1,马上获取原生DOM内容
原因: Vue更新DOM是异步的
目标:等DOM更新后, 触发此方法里函数体执行
1、语法: this.$nextTick(函数体)
1. 获取原生DOM元素
我是一个孤独可怜又能吃的h1
2. 获取组件对象 - 可调用组件内一切
3. vue更新DOM是异步的
{{ count }}
1、data改变更新DOM是同步还是异步的?
异步
2、我们可以在哪里访问到更新后的DOM呢?
this.$nextTick里的函数体
updated生命周期钩子函数
$nextTick还有什么使用场景呢?
点击按钮自身隐藏, 出现输入框并马上处于激活状态
效果演示:
1、$nextTick函数原地返回什么?
Promise对象
2、如何在JS中主动触发标签的事件呢?
获取到DOM对象, 调用事件方法
name的作用
这个时候被递归的组件name必写
一个组件需不需要被缓存,也是需要通过name属性来控制。
显示组件的name,语义化
问题1: 如何切换2个组件, 互斥的显示或隐藏呢?
问题2: 不用v-if可以实现吗?有没有简单的方式?
多个组件使用同一个挂载点,并动态切换,这就是动态组件
完成一个注册功能页面, 2个按钮切换, 一个填写注册信息, 一个填写用户简介信息
效果如下:
下面显示注册组件-动态切换:
在App.vue - 引入01_UseDynamic.vue并使用显示
vue内置component组件, 配合is属性, 设置要显示的组件名字
问题1: 频繁的切换会不会导致组件频繁创建和销毁呢?
问题2: 性能高不高呢?
问题3: 如何避免这个问题?
组件切换会导致组件被频繁销毁和重新创建, 性能不高
使用Vue内置的keep-alive组件, 可以让包裹的组件保存在内存中不被销毁
演示1: 可以先给UserName.vue和UserInfo.vue 注册created和destroyed生命周期事件, 观察创建和销毁过程
演示2: 使用keep-alive内置的vue组件, 让动态组件缓存而不是销毁
Vue内置的keep-alive组件 包起来要频繁切换的组件
02_UseDynamic.vue
补充生命周期
keep-alive可以提高组件的性能, 内部包裹的标签不会被销毁和重新创建, 触发激活和非激活的生命周期方法。
如何知道组件被切走了, 还是切换回来了呢?
被缓存的组件不再创建和销毁, 而是激活和非激活
补充2个钩子方法名:
activated – 激活时触发
deactivated – 失去激活状态触发
如何知道缓存的组件是出现还是消失了?
activated – 获得激活状态
deactivated – 失去激活状态
include="组件Aname"
组件A会被缓存,其他组件不缓存
exclude="组件A的name"
组件A不缓存,其他组件缓存
问题1: 组件里的数据不确定可以怎么做?
问题2:组件里的标签不确定怎么办呢?
用于实现组件的内容分发, 通过 slot 标签, 可以接收到写在组件标签内的内容
vue提供组件插槽能力, 允许开发者在封装组件时,把不确定的部分定义为插槽
插槽例子:
以前折叠面板案例, 想要实现不同内容显示, 我们把折叠面板里的Pannel组件, 添加组件插槽方式
03/Pannel.vue - 组件(直接复制)
芙蓉楼送辛渐
{{ isShow ? "收起" : "展开" }}
寒雨连江夜入吴,
平明送客楚山孤。
洛阳亲友如相问,
一片冰心在玉壶。
views/03_UserSlot.vue - 使用组件(直接复制)
框: 在这个基础重复使用组件
案例:折叠面板
views/03_UseSlot.vue - 组件插槽使用
案例:折叠面板
我是内容
寒雨连江夜入吴,
平明送客楚山孤。
洛阳亲友如相问,
一片冰心在玉壶。
问题1: 使用我封装组件的人, 不给slot传标签, 怎么办?
问题2: 可否设置默认内容?
如果外面不给传, 想给个默认显示内容
夹着内容默认显示内容, 如果不给插槽slot传东西, 则使用夹着的内容在原地显示
默认内容
问题1: 组件内有2处以上不确定标签怎么办?
问题2: 能否给slot起个名字呢?
当一个组件内有2处以上需要外部传入标签的地方
传入的标签可以分别派发给不同的slot位置
v-slot一般用跟template标签使用 (template是html5新出标签内容模板元素, 不会渲染到页面上, 一般被vue解析内部标签)
components/04/Pannel.vue - 留下具名slot
{{ isShow ? "收起" : "展开" }}
views/04_UseSlot.vue使用
案例:折叠面板
芙蓉楼送辛渐
我是内容
我是标题
寒雨连江夜入吴,
平明送客楚山孤。
洛阳亲友如相问,
一片冰心在玉壶。
问题: 使用插槽时, 想使用组件内的变量?
子组件里值, 在给插槽赋值时在父组件环境下使用
复习: 插槽内slot中显示默认内容
例子: 默认内容在子组件中, 但是父亲在给插槽传值, 想要改变插槽显示的默认内容
components/05/Pannel.vue - 定义组件, 和具名插槽, 给slot绑定属性和值
芙蓉楼送辛渐
{{ isShow ? "收起" : "展开" }}
{{ defaultObj.defaultOne }}
views/05_UseSlot.vue
案例:折叠面板
{{ scope.row.defaultTwo }}
问题:作用域插槽具体使用场景有哪些呢?
了解作用域插槽使用场景, 自定义组件内标签+内容
案例: 封装一个表格组件, 在表格组件内循环产生单元格
准备MyTable.vue组件 – 内置表格, 传入数组循环铺设页面, 把对象每个内容显示在单元格里
准备UseTable.vue – 准备数据传入给MyTable.vue使用
components/06/MyTable.vue - 模板(直接复制)
序号
姓名
年龄
头像
views/06_UseTable.vue - 准备数据, 传入给MyTable.vue组件里循环使用
list: [
{
name: "小传同学",
age: 18,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg",
},
{
name: "小黑同学",
age: 25,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg",
},
{
name: "智慧同学",
age: 21,
headImgUrl:
"http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg",
},
],
例子: 我想要给td内显示图片, 需要传入自定义的img标签
正确做法:
在MyTable.vue的td中准备占位, 但是外面需要把图片地址赋予给src属性,所以在slot上把obj数据绑定
components/06/MyTable.vue - 正确代码
序号
姓名
年龄
头像
{{ index + 1 }}
{{ obj.name }}
{{ obj.age }}
{{ obj.headImgUrl}}
在UseTable使用MyTable的时候, template上v-slot绑定变量, 传入img组件设置图片地址
我们为什么要使用作用域插槽?
可以让组件更加灵活的适用于不同的场景和项目
插槽可以自定义标签, 作用域插槽可以把组件内的值取出来自定义内容
问题1: Vue内置指令不满足要求?
问题2: 能否自己定义一些指令来使用?
目标:获取标签, 扩展额外的功能
语法
export default {
directives: {
focus: {
inserted(el){
el.focus()
}
}
}
}
语法
// 全局指令 - 到处"直接"使用
Vue.directive("gfocus", {
inserted(el) {
el.focus() // 触发标签的事件方法
}
})
全局注册自定义指令, 哪里都能用, 局部注册, 只能在当前vue文件里用
我们为什么要自定义指令?
在Vue内置指令满足不了需求时, 可以自己定义使用
问题: 指令能不能传值呢?
目标: 使用自定义指令, 传入一个值
// 目标: 自定义指令传值
Vue.directive('color', {
inserted(el, binding) {
el.style.color = binding.value
},
update(el, binding) {
el.style.color = binding.value
}
})