MVVM
MVVM 即模型-视图-视图模型。
模型 指的是后端传递的数据; 视图 指的是所看到的页面。
视图模型 是mvvm模式的核心,它是连接view和model的桥梁。
它有两个方向:
一是将 模型 转化成 视图 ,即将后端传递的数据转化成所看到的页面。 实现的方式是:数据绑定。
二是将 视图 转化成 模型 ,即将所看到的页面转化成后端的数据。 实现的方式是:DOM 事件监听。 这两个方向都实现的,我们称之为数据的双向绑定。
优势
1.低耦合。在后端接口提供前可完成Controller和View的开发工作。视图可以独立于Model变化 和修改。
2.可复用。可以把一些视图逻辑放到一个ViewModel里面,让很多View重用这段视图逻辑。
3.独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
4.可测试。由于ViewModel把逻辑分离出来,测试可以针对ViewModel来写。
缺点
1. Bug 很难被调试 : 因为使⽤双向绑定的模式,当你看到界⾯异常了,有可能是你 View 的代码有 Bug ,也可能是 Model 的代码有问题。数据绑定使得⼀个位置的Bug 被快速传递到别的位置,要定位原始出问题的地⽅就变得不那么容易 了。另外,数据绑定的声明是指令式地写在View 的模版当中的,这些内容是没办法去打断点 debug 的。
2. ⼀个⼤的模块中 model 也会很⼤,虽然使⽤⽅便了也很容易保证了数据的⼀致性,当时⻓期持有,不释放内存就造 成了花费更多的内存。
3. 对于⼤型的图形应⽤程序,视图状态较多, ViewModel 的构建和维护的成本都会⽐较⾼。
CMD命令操作
cmd是什么
Windows 命令提示符(即 cmd)是 Windows 系统的一种命令行操作工具,用户可以通过输入命令来完成各种各样的系统或程序操作。
如何打开cmd命令窗口
方法一:开始菜单 -> Windows 系统 -> 命令提示符。
方法二:按下快捷键 Win + R 打开运行,输入 cmd 回车。
方法三:点击任务栏搜索按钮,搜索 cmd 并打开。
方法四:在资源管理器的地址栏输入 cmd 并回车,cmd 打开后会自动定位到当前目录。
方法五:右键点击开始菜单的 Win 图标 -> 命令提示符。
每条命令输入后,回车运行。命令正确则执行完毕后回到
>
状态;命令错误返回错误信息。常用命令
盘符名称+冒号——盘符切换
dir——查看当前路径下的文件列表
cd目录——进入单级目录 (tab补足目录名称)
cd..——回退到上一级目录
cd 目录一\目录二\...——进入多级目录
cd\——回退到盘符目录
cls——清屏
exit——退出命令提示符窗口
calc——启动计算机
cleanmgr——启动磁盘清理
notepad——启动记事本
magnify——启动放大镜
mspaint——启动画图板
osk——启动屏幕键盘
CDN
什么是CDN
CDN的全称Content Delivery Network,是指内容分发网络。通过构建分布式的内容分发发网络,用户可以就近获取所需内容,这样可以提高用户访问的响应速度和命中率。有些服务提供商会免费提供常用框架的 JavaScript 文件的 CDN 服务(可以直接使用),但是在商业化应用的过程中,需要要注意版权问题。
特点
本地Cache加速:提高了企业站点(尤其含有大量图片和静态页面站点)的访问速度,并大大提高以上性质站点的稳定性。
镜像服务:消除了不同运营商之间互联的瓶颈造成的影响,实现了跨运营商的网络加速,保证不同网络中的用户都能得到良好的访问质量。
远程加速:远程访问用户根据DNS负载均衡技术智能自动选择Cache服务器,选择最快的Cache服务器,加快远程访问的速度。
带宽优化:自动生成服务器的远程Mirror (镜像) cache服务器,远程用户访问时从cache服务器上读取数据,减少远程访问的带宽、分担网络流量、减轻原站点WEB服务器负载等功能。
集群抗攻击:广泛分布的CDN节点加上节点之间的智能冗余机制,可以有效地预防黑客入侵以及降低各种D.D.o.S攻击对网站的影响,同时保证较好的服务质量。
ES6-键值对
什么是键值对
键值对('key = value') 顾名思义,每一个键会对应一个值。
例:
a:身份证号和你本人是绑定的关系。每一个身份证号(键)都会对应一个人(值)。
b:我们在登录微信或者游戏时,需要输入手机号验证身份。系统会向该手机号发送一条验证短信。
这里的手机号码(键),对应的接收用户就是值。
每个键对应响应的值,当按下响应的键时,就会输出响应的结果。
键:就是存的值的编号。
值:就是要存放的数据。
let和const
(1)let声明变量,可变
const定义常量(实际指的是变量和的内存地址),不可变,只能在其声明或定义的代码块内有效
let:ES6新增,用于声明变量,有块级作用域。
var:ES5中用于声明变量的关键字,存在各种问题。
(2)let命令存在块级作用域分别用var和let声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
字符串新写法 加强版的引导
console.log(`积极 \n 向上`);
内容中可以直接出现换行符console log(`积极 向上`);
(3)定义变量let name = `萧萧下`;
let skill = `一决高下`;
(4)字符串中嵌入变量document.write(`${name}的主要技能是${skill}`)
字符串声明与方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//声明字符串
let str1 = '啦啦啦啦啦';
let str2 = "lllllllll";
let str3 = `kkkkkkkkk`;
//判断一个字符串在不在某个字符串里面
let index1 = str1.indexOf('啦啦');
console.log(index1);
//截取字符串
let str4 = str1.substr(2,3)
console.log(str4);
//修改字符串
let str5 = str2.replace('kk','ll')
console.log(str5);
//大小写转换
console.log('ASDF'.toLowerCase());
console.log('asdf'.toUpperCase());
console.log('中文不存在大小写'.toLowerCase());
</script>
</body>
</html>
生命周期钩子
什么是生命周期?
Vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能
Vue实例生命周期的图示:
生命周期函数
1、beforeCreate(创建前) 一切未开始。
2、created(创建后) 完成了对数据的观测,属性和方法的运算,初始化事件,$el属性还没有显示出来。
3、beforeMount(载入前) 完成了编译模板,并生成了真实的dom,但还没有挂载html到页面上。
4、mounted(载入后) 完成了把dom挂载到页面上,此过程中可以进行ajax交互。
5、beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。
6、updated(更新后) 调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
7、beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
8、destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。
每个周期具体适用于哪些场景
(1)beforeCreate:可以在这加loading事件,在加载实例时触发。
(2)created:初始化完成时的事件写在这里,如在这里结束loading,异步请求也适合在这里调用。
(3)mounted:挂载元素,获取到dom节点。
(4)updated:如果对数据统一处理,在这里写上相应的函数。
(5)beforeDestroy:清空定时器等。
数组的侦听
侦听器的基本结构
<script>
// 【侦听器】
// 作用:用来侦听数据有没有变化,一旦有变化就调用函数。
// 语法: 在和data、methods这些平级的位置写一个 watch
new Vue({
el:'',
data:{},
methods:{},
// 侦听器
watch:{
// 参数一:改变后的值。
// 参数二:改变前的值。
要侦听的数据(newValue,oldValvue){
}
}
})
</script>
侦听器的基本使用
<div id="app">
<button @click="msg='哈哈哈哈哈'">修改msg的值</button>
<p>{ {msg}}</p>
</div>
<script src="./vue.js"> </script>
<script>
new Vue({
el:'#app',
data:{
msg:'嘎嘎嘎嘎'
},
//写侦听器的地方
watch:{
// 侦听器的数据变化
// 基本数据类型,这两个参数有意义
msg(newValue,oldValue){
// 侦听到数据变化之后,需要完成的行为
console.log('数据改变了',newValue,oldValue);
}
}
})
</script>
侦听器在数组的使用
<div id="app">
<ul>
<li v-for="item in list">{ {item}}</li>
</ul>
<button @click="list.push('喜羊羊')">添加一个项</button>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
list:['小黄很没用','小钟很事多','小卢恋爱脑']
},
watch:{
list(newValue,oldVaule){
console.log('数据的改变了',newValue,oldVaule,);
}
}
})
</script>
对数组进行侦听】
数组是应用类型,存在比较复杂的侦听规则。
从理论上说,修改一个数组的内容,比如修改数组中某个元素的值,或者给数组添加新的元素,都不会修改数组本身的地址。
为此.Vue.is对数组做了特殊处理,使得使用标准的数组操作方法对数组所做的修改,都可以被侦听到。
1.Vue不能检测以下数组的变动:
a.当你利用索引值直接设置一个数组时,例如:vm.items[index0fItem] = newValue
b.当你修改数组的长度时,例如:vm.items.length = newlength
2.使用标准方法修改数组可以被侦听到
push() 尾部添加 pop()尾部删除
unshift()头部添加
shift()头部删除
splice()删除、添加、替换
sort()排序
reverse()逆序
(Vue将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新,以上就是被包裹的方法。)
<div id="app">
<button @click="list.pop()">删除一个项</button>
<button @click="list.push('喜羊羊')">添加一个项</button>
<ul>
<li v-for="item in list">{ {item}}</li>
</ul>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
list:['小黄很没用','小钟很事多','小卢恋爱脑']
},
watch:{
// 复杂数据类型,这两个参数没有意义,因为地址没变
// 所以复杂类型中,一般不会写这两个参数,因为这两个参数的值是一样的,就是写也只写一个。
list(newValue,oldVaule){
console.log('数据的改变了',newValue,oldVaule,);
}
}
})
</script>
watch:{
这种写法侦听不到obj对象内部属性的变化,
只能侦听到obj对象指向的变化。
obj(){
console.log('obj变化了');
},
如果想侦听到对象里属性的变化.
侦听obj里name的变化(要记得加引号)
"obj.name"(){
console.log('name变化了');
},
可是这样写只能侦听一个属性。
如果希望侦听到对象里所有属性的变化,就要开启深度侦听。
obj:{
/当有变化会调用的函数
handler(){
console.log('obj的属性变化了');
},
开启深度侦听
deep:true,
号要不要当前页面一打开就立即调用handler函数。
给true表示立即调用,默认是flase。(代表只有改动了才调用
immediate:true
}
}
<!-- 对对象进行侦听 --> <div id="app"> <p>{ { obj.name }} --- { { obj.age }} --- { { obj.height }}</p > <button @click = "obj.name ='rose'">修改obj的name属性</button> <button @click = "obj.age = 30">修改obj的age属性</button> <button @click = "obj = {name:'andy',age:99} ">修改obj的指向</button> </div> <script src="./vue.js"></script> <script> new Vue({ el:'#app', data:{ obj:{ name:'小黄玩不过植物大战僵尸', age:40, height:160 } }, watch:{ obj:{ handler(){ console.log('obj的属性变化了'); }, } } }) </script>
在数组中使用侦听器总结:
1.彻底替换为一个新数组,那么可以被侦听到。
2.如果使用了push()等标准的数组操作方法,那么可以被侦听到。
3.如果直接修改数组的元素,那么无法被侦听到。
(解决方法:使用$set(()方法修改元素的值。Vue3语法。)
不要使用length属性来修改数组长度,而改用其他标准方法显示数组长度的变化。
<div id="app">
<button @click="list.pop()">删除一个项</button>
<button @click="list.push('喜羊羊')">添加一个项</button>
<!-- 利用索引值改变数组时,不能被侦听到 -->
<button @click="list[0]='没用'">修改第一项</button>
<button @click="list.splice(1,0,'小彭很厉害')">第二添加</button>
<ul>
<li v-for="item in list">{ {item}}</li>
</ul>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
list:['小黄很没用','小钟很事多','小卢恋爱脑']
},
watch:{
// 复杂数据类型,这两个参数没有意义,因为地址没变
// 所以复杂类型中,一般不会写这两个参数,因为这两个参数的值是一样的,就是写也只写一个。
list(){
console.log('数据的改变了');
}
}
})
</script>
事件对象属性
事件对象
浏览器中的事件都是以对象的形式存在的,在标准DOM中,规定事件对象必须作为唯一的参数传给事件处理函数。
事件对象中的常见属性
标准DOM 类型 读/写 说明 altKey Boolcan 读写 按下 Alt 键则为 true,否则为 false button Integer 读写 鼠标事件,值对应按下的鼠标键 cancelabie Boolcan 只读 是否可以取消事件的默认行为 stopPropagation() Function N/A 阻止事件向上冒泡 clientX Intege 只读 鼠标在客户端区域(当前窗口)的水平坐标,不包括工具栏、滚动条等 clientY Integer 只读 鼠标在客户端区域(当前窗口)的垂直坐标,不包括工具栏、滚动条等 ctrlKey Boolcan 只读 按下 Ctrl 键则为 true,否则为 false relatedTarget Element 只读 鼠标正在进入/离开的元素 charCode Integer 只读 按下按键的 Unicode 值 keyCode Integer 读写 按下按键时为 0,其余情况下为按下按键的数字代号 detail Integer 只读 鼠标按键的单击次数 preventDefault() Function N/A 阻止事件的默认行为 screenX Integer 只读 鼠标相对于屏幕的水平坐标 screenY Integer 只读 鼠标相对于屏幕的垂直坐标 shifKey Boolean 只读 按下 Shift 键则为 true,否则为 false target Element 只读 引起事件的元素/对象 type String 只读 事件的名称 三.事件类别
·用户界面事件:涉及与 BOM 交互的通用测览器事件。
· 焦点事件:在元素获得或失去焦点时触发的事件。
·鼠标事件:使用鼠标在页面上执行某些操作时触发的事件。·滚轮事件:使用鼠标滚轮时触发的事件。
·输入事件:向文档中输入文本时触发的事事件。
·键盘事件:使用键盘在页面上执行某些接操作时触发的事件。·输入法事件:使用某些输入法时触发的真事件。
事件修饰符
介绍
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 事件修饰符
event.preventDefault()/阻止默认行为或者event.stopPropogation()/阻止事件冒泡。
以上方法需要处理DOM事件细节,代码繁琐。
为了解决这个问题,Vue.js提供了事件修饰符。
修饰符是以点开头的指令后缀来表示的。 -->
<!-- stop 阻止冒泡事件继续传播 -->
a v-on:click.stop="doThis"></ a>
<!-- .self 当事件目标是当前元素自身时,触发事件 -->
<ul @click.self="ulclick"></ul>
<!-- .capture 将原本默认的冒泡方式改为捕捉方式 -->
<!-- .prevent 阻止事件默认行为 -->
<!-- @submit.prevent 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- .stop.prevent 修饰符可以串联,既阻止冒泡又阻止默认行为。-->
<a v-on:click.stop.prevent="doThat"></ a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
</body>
</html>
事件修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app" >
<ul @click.self="ulClick">
<li @click.stop="liClick">小黄过不了植物大战僵尸</li>
<li @click="liClick">小邹玩游戏输不起</li>
<li>小彭很厉害</li>
</ul>
</div>
<script src="../vue.js"></script>
<script>
new Vue ({
el:'#app',
methods:{
divClick(){
console.log('div');
},
ulClick(){
console.log('ul');
},
liClick(evt){
console.log('li');
}
}
})
</script>
</body>
</html>
事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="outer" @click="">
<button @click="click"> click me </button>
</div>
<script>
// 事件冒泡和事件捕获分别由微软和网景公司提出,是为了解决页面中事件流(事件发生顺序)的问题。
// 事件冒泡:
// 微软提出了名为事件冒泡(event bubbling)的事件流。
// 事件冒泡可以形象的比喻成把一颗石头投入水中,泡泡会一直从水底冒出水面。
// 也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
// 因此在事件冒泡的概念下在button按钮发生click事件的顺序应该是button→div→body→html→document.
// 事件捕获:
// 网景提出另一种事件流名为事件捕获(event capturing)。11 与事件冒泡相反,事件会从最外层开始发生,直到具体的元素。
// 因此在事件捕获的概念下在button按钮发生click事件的顺序应该是document→html→bodv→div→button。
// 后来W3C采用折中的方式,平息了网景和微软之间的战争,制定了统一的标准--先捕获在冒泡。
</script>
</body>
</html>
事件方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 【事件方法】
@click:当单击元素时,发生click事件。
@dbclick: 当双击元素时,发生dbclick事件。
@focus:当元素获得焦点时,发生focus事件。
@blur:当元素失去焦点时发生blur事件。
@submit:当提交表单时,发生submit事件。
@keydown:当键盘被按下时,发生keydown事件。
@keyup:当键盘被松开,发生keyups事件。
@mouse enter: 当鼠标指针穿过(进入)被选元素时,会发生mousedown事件。
@mouse down:当鼠标指针移动到元素上方,并按下鼠标左键,会发生mousedown事件。
@mouse leave:当鼠标离开被选元素时,会发生mouseleave事件。
@mouse move: 当鼠标指针在指定的元素中移动时,会发生 mousemove 事件。
@mouse out: 在鼠标指针离开被选元素或任意子元素时都会被触发。
@mouse over:当鼠标指针位于元素上方时,会发生 mouseover 事件。
@mouse up:当鼠标指针移动到元素上方,并松开鼠标左键时,会发生 mouseup 事件。 -->
<!-- 【事件】
JavaScript中的事件,可以理解就是在HTML文档或者浏览器中发生的一种交互操作,使得网页具备互动性。
常见的有加载事件、鼠标事件。
【事件流】
由于DOM是一个树结构,如果在父子节点绑定事件时候,当触发子节点的时候,就存在一个顺序问题,这就涉及到了事件流。
页面触发一个事件时,会按照一定的顺序来响应事件,事件的响应过程为事件流。
【js的事件流三阶段】
事件捕捉阶段(capture phrase):事件开始由顶层对象触发,然后逐级向下传播,直到目标元素;
处于目标阶段(target phrase):处于绑定事件的元素上;
事件冒泡阶段(bubbling phrase):事件由具体的元素先接收,然后逐级向上传播,直到不具体的元素;
(事件捕获是从上到下,而事件冒泡,是从下到上。) -->
<div id="app">
<!-- 当点击这个按钮,就调用fn1函数 -->
<button v-on:click="fn1">点我啊</button>
<!-- 当双击这个按钮,就调用fn1函数 -->
<button v-on:dblclick="fn1">双击666</button>
<!-- 当移入这个按钮,就调用fn2函数 -->
<button v-on:mouseenter="fn2">移入我</button>
<!-- 简写形式:把v-on:改成@就是简写形式 -->
<h4>以下是简写形式</h4><hr>
<!-- 当点击这个按钮,就调用fn1函数 -->
<button @click="fn1">点我啊</button>
<!-- 当双击这个按钮,就调用fn1函数 -->
<button @dblclick="fn1">双击666</button>
<!-- 当移入这个按钮,就调用fn2函数 -->
<button @mouseenter="fn2">移入我</button>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
//Vue中放方法的地方
methods:{
fn1(){
alert('点我干哈?')
},
fn2(){
alert('你想干哈?')
}
}
})
</script>
</body>
</html>