Vue全家桶
Vue全家桶
课程概述
前端框架—> Vue 2.0 —> Vue3.0
- VUE基础
- VUE-CLI
- VUE-ROUTER
- VUEX
- ELEMENT-UI
- VUE3.0
基础内容 ES6
全称ECMAScript6.0,是JavaScript(ECMAScript的一种实现)的下一个版本标准,2015.06发布,主要为了解决ES5先天的不足,比如JavaScript里没有类的概念,但是目前浏览器的JavaScript是ES5版本,大多数高版本浏览器也支持ES6,不过只实现了ES6的部分特性和功能。
ES新特性指的是JavaScript的新特性,包括ES6-ES11版本。
ECMA:European Computer Manufacturers Association,中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发、认可电信和计算机标准。
ECMAScript:由ECMA国际通过ECMA-262标准化的脚本程序设计语言。
- 学习ES6的原因:
- ES6的版本变动最多,具有里程碑的意义。
- ES6加入许多新的语法特性,编程实现更加简单、高效。
- ES6是前端发展的趋势,就业的必备技能。
浏览器兼容性表格:ECMAScript 6 compatibility table (kangax.github.io)
下面进入Vue2.0学习(135P)
第一章 VUE核心
1.1 Vue简介
一套用于构建用户界面的渐进式JavaScript框架
VUE可以自底向上逐层的应用
简单应用:只需要一个轻量小巧的核心库
复杂应用:可以引入各式各样的VUE插件
开发者:尤雨溪
VUE特点:
- 采用组件化模式,提高代码的复用率,且让代码更好维护。
- 声明式编码,让编码人员无需直接操作DOM,提高开发效率。
JS的基础知识:
- ES6语法规范
- ES6模块化
- 包管理器
- 原型、原型链
- 数组常用方法
- axios
- promise
1.2 初识VUE
1 |
|
- 总结:
- 想让vue工作,就必须创建一个vue实例,并且要传入一个配置对象
- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
- root容器里的代码称为【Vue模板】
- root容器的作用:
- 为VUE提供模板
- 告知VUE的工作成果展示位置
1.3分析Hello案例
1 |
|
注意区分JS表达式和JS代码
- 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
- a
- a+b
- demo(1)
- 代码
- if(){}
- for(){}
- JS表达式是一种特殊的JS代码(语句)
- 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
总结:
- 容器和VUE实例一一对应
- 动态数据交付VUE实例托管
- 真实开发中只有一个VUE实例,并且会配合组件一起使用
- 中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性
- 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新
1.4 模板语法
1 |
|
- VUE模板语法有两大类:
- 插值语法
- 功能:用于解析标签体内容
- 写法:,xxx是JS表达式,且可以直接读取到data中的所有属性,不包括用户自定义属性
- 指令语法
- 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件……)
- 举例:v-bind:herf=”xxx” 或 简写为 :href=”xxx”,xxx同样要写js表达式,且可以直接读取到data中的所有属性
- 备注:VUE中有很多指令,且形式都是:v-???,此处只是拿v-bind举例
- 插值语法
1.5 数据绑定
错误示范:v-model只能应用于表单类元素上(输入类,要有value属性)
1 |
|
- 总结
- 单向绑定(v-bind):数据只能从data流向页面
- 双向绑定(v-model):数据不仅能data流向页面,还可以从页面流向data
- 备注:
- 双向绑定一般都应用于表单类元素上(如:input、select)
- v-model:value = “xxx” 可以**简写为v-model=”xxxx”**因为v-model默认收集value值
1 |
|
1.6 el与data的两种写法
效果
1 |
|
1 |
|
组件复用data必须为函数
data与el的两种写法
- el的两种写法
- new Vue的时候配置el属性
- 先创建Vue实例。随后再通过vm.$mount(‘#root’)指定el的值
- data的两种写法
- 对象式
- 函数式
- 选择:目前都可以使用,但是学习了组件后,data必须使用函数式,否则会报错
- 重要原则
- 由VUE管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是VUE实例了(而是Windows实例)
- el的两种写法
1.7 理解MVVM模型
- M:模型(Model) :对应 data 中的数据
- V:视图(View) :模板代码
- VM:视图模型(ViewModel) : Vue 实例对象
此在文档中经常会使用 vm
(ViewModel 的缩写) 这个变量名表示 Vue 实例。
- 观察发现:
- data中所有属性,最后都出现在了vm身上
- vm身上所有属性及VUE原型上所有属性,在VUE模板中都可以直接使用
1.8 回顾Object.defineProperty方法
回顾Object.defineProperty方法
作用:给对象添加/定义属性
添加值
1 |
|
age不可以被枚举(不参与遍历)
1 |
|
要实现枚举:
1 |
|
无法改变值
实现可改变:
1 |
|
不可删除其中的值
实现可删除:
1 |
|
实现age随变量的变化而动态变化
1 |
|
1 |
|
表面上更改了age属性,实际上并没有改掉,因为number没有变化
改正:
1 |
|
总结:age属性值现用现取
1.9 理解数据代理
1 |
|
1.10 Vue中的数据代理
1 |
|
当对vm进行访问的时候,getter开始工作,把别的地方(data)的name拿过来使用;当有人通过vm修改name,setter开始工作。读写都是使用的data中的属性。
需要验证
1.验证getter:
2.验证setter:
vm将data数据存储在自己内部,称为_data,通过_data可以访问name和address(不便于编码,所以用后者);由于使用了数据代理,也可以直接访问name和address。
注意_data和代码data并不相同,这里涉及到了数据劫持,后续会学习。(数据劫持的目的是为了实现一个功能:感知data中的数据被修改,并将修改结果更新展示在页面里,即响应式)
1 |
|
原因:一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新。
数据代理图示
总结
- Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
- Vue中数据代理的好处:更加方便地操作data中的数据
- 基本原理:
- 通过Object.defineProperty()把data对象中的所有属性添加到vm上。
- 为每一个添加vm上的属性,都指定一个getter和setter。
- 在getter/setter内部去操作(读/写)data中对应的属性。
1.11 事件处理
1 |
|
点击按钮,调用showInfo函数,所以a为返回的事件对象,下面是event的target。
showInfo中的this的含义:此处this就是vm
易错易混:箭头函数this指向Windows
因此,我们遵循原则:接受Vue管理的函数,最好都写成普通函数。
事件绑定的简写形式:
1 |
|
功能需求:事件触发后,传参。
1 |
|
需要解决的BUG:这样写代码会丢失event,再也不能使用event了。
解决方法:
1 |
|
methods中的方法与Vue实例:
回调方法写在methods中,不要写在data中,因为会自动进行数据代理,添加无意义的getter和setter。(函数只是调用的,不需要更改)
总结
事件的基本使用:
- 使用v-on:xxx 或 @click绑定事件,其中xxx为事件名称
- 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,不要使用箭头函数!!!否则this指向的就不再是vm了
- methods中配置的函数,都是被Vue所管理的函数,,this指向的是vm或者组件实例对象
- @click = “demo” 和 @click = “demo($event)” 效果一致,但是后者可以传参
1.12 事件修饰符
阻止a标签的跳转行为
1 |
|
vue中的阻止方法:
prevent即事件修饰符,阻止默认行为。
6个事件修饰符
修饰符名称 | 功能 |
---|---|
prevent | 阻止默认事件(常用) |
stop | 阻止事件冒泡(常用) |
once | 事件只触发一次(常用) |
capture | 使用事件的捕获模式 |
selt | 只有event.target是当前操作的元素才是触发事件 |
passive | 事件的默认行为立即执行,无需等待事件回调执行完毕 |
prevent:略
stop
事件冒泡
1 |
|
阻止事件冒泡
JS
Vue
1 |
|
once
效果
1 |
|
capture
1 |
|
点击div2区域后触发的效果:
点击div2先经过事件捕获过程,随后才是事件冒泡,默认情况下,冒泡阶段处理事件。
捕获阶段,由外往内;冒泡阶段,由内往外。
对外部盒子使用capture:
1 |
|
self
1 |
|
点击后的效果:
添加stop事件修饰符:
1 |
|
passive
1 |
|
@scroll(滚轮、侧拉条、上下键触发)
@wheel(只有滚轮有效,上下键、侧拉条失效)
@wheel会延迟滚动,这时候可以使用passive修饰符修饰;而@scroll不需要,因为会立即执行默认行为。passive在移动端使用较多。
1.13 键盘事件
案例:在输入框中输入内容后,按下Enter后,在控制台显示。
1 |
|
问题:没有按Enter,控制台输出input框内容。
代码改进
vue中的处理方式:
1 |
|
Vue常用按键别名
按键名 | 别名 |
---|---|
回车 | enter |
删除 | delete(捕获“删除”和“退格”键) |
退出 | esc |
空格 | space |
换行 | tab(特殊,需要配合keydown来使用) |
上 | up |
下 | down |
左 | left |
右 | right |
为了方便,原来的首字母大写改成了全部小写,但是首字母大写也能实现功能。
1 |
|
Vue中没有别名的按键处理
注意:Vue中未提供别名的按键,可以使用按键原始的key值去绑定,但要注意转换为keabab-case(短横线命名)。
对于CapsLock键:
错误(没有效果)
1 |
|
正确
1 |
|
注意:不是所有键位都可以绑定事件。
特殊系统修饰键
ctrl、alt、shift、meta(Win键-Windows / Command键-Mac)
- 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发(也可以正常工作,只是一般不用)
- 配合keydown使用:正常事件触发
例如:tab键,本身功能是把焦点从当前元素上切走。而且是跟keyup事件绑定,按下tab键之后,就失去了焦点,事件无法触发,所以需要使用keydown实现。
1 |
|
效果:先触发控制台输出,再触发焦点切换功能。
使用KeyCode指定具体的按键(不推荐)
例如Enter,键码为13。
1 |
|
KeyboardEvent.keyCode标准已经从Web标准移除,未来浏览器也许会停止支持,所以尽量不要使用该特性。(因为不同键盘编码可能不统一)
定制按键别名
Vue.config.keyCodes.自定义键名 = 键码 ,可以去定制按键别名。
例:
1 |
|
1 |
|
注意:别名不能带大写字母!!!
1.14 事件总结
1 |
|
要求:既需要阻止冒泡,又需要阻止跳转。
方法一:
1 |
|
方法二:
1 |
|
修饰符可以连续书写
案例:按下Ctrl + Y的时候控制台输出
1 |
|
1.15 计算属性 computed
效果图
使用插值语法实现
1 |
|
实现截取部分输入,丢弃过长输入。
1 |
|
风格指南
随着要求越多,{{}}`中的代码会越来越长,虽然不报错,但是这样违背了VUE的风格指南。
#### 使用methods语法实现
##### 易错易混点
methods
注意:fullName中的this是当前vue的实例对象
,表面上传了一个参数,但实际上,传递了两个,第一个参数一定是前面的time!!!而第二个参数才是括号中的内容。1
2
3
4
5methods:{
fullName(){
return this.firstName + '-' + this.lastName;
}
}1
2姓名: <span>{{fullName()}}</span>
<!--将fullName的返回值插入到此处-->1
姓名: <span>{{fullName}</span>
1
2
3
4fullName(){
console.log('@@@');
return this.firstName + '-' + this.lastName;
}1
2
3
4
5
6fullName:{
get(){
console.log('get被调用!');
return this.firstName + '-' + this.lastName;
}
}1
2
3
4姓名: <span>{{fullName}}</span>
姓名: <span>{{fullName}}</span>
姓名: <span>{{fullName}}</span>
姓名: <span>{{fullName}}</span>1
2
3set(value){
console.log('set被调用了',value);
}1
2
3
4
5
6
7computed: {
// fullName:function(){
fullName(){
console.log('get被调用!');
return this.firstName + '-' + this.lastName;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<body>
<!--准备一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
isHot: true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot;
}
}
})
</script>1
2
3
4<div id="root">
<h2>今天天气很一般</h2>
<button @click="changeWeather">切换天气</button>
</div>1
2
3
4<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="isHot = !isHot">切换天气</button>
</div>1
2<!--点击后弹窗-->
<button @click="alert(1)">切换天气</button>1
<button @click="window.alert(1)">切换天气</button>
1
2
3
4data: {
isHot: true,
window //window:window
}1
2
3
4
5
6
7
8watch:{
isHot:{
immediate:true, //作用:初始化时让handler调用一下。
handler(newValue,oldValue){
console.log('isHot改变了',newValue,oldValue);
}
}
}1
2
3
4
5vm.$watch('isHot',{
immediate:true, //作用:初始化时让handler调用一下。
handler(newValue,oldValue){
console.log('isHot改变了',newValue,oldValue);
})1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<body>
<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">点我让a++</button>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
numbers:{
a:1,
b:1
}
},
watch:{
'numbers.a':{
handler(newValue,oldValue){
console.log('a改变了',newValue,oldValue);
}
}
}
})
</script>1
2
3
4
5
6
7watch:{
numbers:{
handler(newValue,oldValue){
console.log('number改变了',newValue,oldValue);
}
}
}1
2
3
4
5
6
7
8watch:{
numbers:{
deep: true,//开启深度监视
handler(newValue,oldValue){
console.log('number改变了',newValue,oldValue);
}
}
}1
vm.numbers.b = 999
1
2
3
4
5
6
7
8watch:{
isHot:{
// immediate:true,
handler(newValue,oldValue){
console.log('isHot改变了',newValue,oldValue);
}
}
}1
2
3
4
5watch:{
isHot(newValue,oldValue) {
console.log('isHot改变了',newValue,oldValue);
}
}1
2
3
4vm.$watch('isHot',{
handler(newValue,oldValue){
console.log('isHot改变了',newValue,oldValue);
})1
2
3vm.$watch('isHot',function(newValue,oldValue){
console.log('isHot改变了',newValue,oldValue);
})1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31<body>
<!--准备一个容器-->
<br /><br />
<br /><br />
<div id="root">
姓: <input type="text" v-model="firstName"><br /><br />
<!--注意:页面上的输入要影响数据本身的变化,应该使用v-model-->
名: <input type="text" v-model="lastName"><br /><br />
姓名: <span>{{fullName}}</span>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三',
fullName: '张-三'
},
watch: {
firstName(newValue){
this.fullName = newValue + '-' + this.lastName;
},
lastName(newValue){
this.fullName = this.firstName + '-' + newValue;
}
}
})
</script>1
2
3
4
5
6
7computed: {
fullName(){
setTimeout(()=>{
return this.firstName + '-' + this.lastName;
},1000)
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34.basic {
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy {
border: 4px solid red;
;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg, yellow, pink, orange, yellow);
}
.sad {
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal {
background-color: skyblue;
}
.mk1 {
background-color: yellowgreen;
}
.mk2 {
font-size: 30px;
text-shadow: 2px 2px 10px red;
}
.mk3 {
border-radius: 20px;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<body>
<div id="root">
<!-- 绑定class样式:字符串写法 -->
<div class="basic" :class="mood" @click="changeMood">{{site}}</div>
</div>
</body>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
site: 'miketaylorjuly123.cn',
mood: 'normal'
},
methods: {
changeMood() {
this.mood = 'happy';
}
}
})
</script>1
2
3
4
5
6
7methods: {
changeMood() {
const arr = ['happy', 'sad', 'normal'];
// Math.floor(Math.random()*3); //随机生成[0,1的小数),随后floor向下取整
this.mood = arr[Math.floor(Math.random() * 3)];
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<body>
<!--准备一个容器-->
<div id="root">
<div class="basic" :style="styleObj">{{site}}</div>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
site: 'miketaylorjuly123.cn',
styleObj:{
fontSize: '40px'
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<body>
<!--准备一个容器-->
<div id="root">
<div class="basic" :style="[styleObj,styleObj2]">{{site}}</div>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
site: 'miketaylorjuly123.cn',
styleObj:{
fontSize: '40px'
},
styleObj2:{
backgroundColor: '#8080ff',
color: 'cyan'
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15new Vue({
el: '#root',
data: {
site: 'miketaylorjuly123.cn',
styleArr: [
{
fontSize: '40px'
},
{
backgroundColor: '#8080ff',
color: 'cyan'
}
]
}
})1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<body>
<!--准备一个容器-->
<div id="root">
<div v-show="a">miketaylorjuly123.cn</div>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
a: false
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<body>
<!--准备一个容器-->
<div id="root">
<div v-if="a">miketaylorjuly123.cn</div>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
a: false
}
})
</script>1
2
3<div v-if="xxx">???</div>
<div v-else-if="xxx">???</div>
<div v-else>???</div>1
2
3
4<div v-if="xxx">???</div>
<div>@@@</div>
<div v-else-if="xxx">???</div>
<div v-else>???</div>1
2
3<div v-if="n%3 ===1">Angular</div>
<div v-else-if="n%3 ===1">React</div>
<div v-else-if="n%3 ===0">Vue</div>1
2
3<div v-if="n%3 ===1">Angular</div>
<div v-if="n%3 ===1">React</div>
<div v-if="n%3 ===0">Vue</div>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<body>
<!--准备一个容器-->
<div id="root">
<div>miketaylorjuly123.cn</div>
<h2>当前的n值:{{n}}</h2>
<button @click="n++">点击n++</button>
<div v-show="n%3 ===1">Angular</div>
<div v-show="n%3 ===2">React</div>
<div v-show="n%3 ===0">Vue</div>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
n:0
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<body>
<!--准备一个容器-->
<div id="root">
<div>miketaylorjuly123.cn</div>
<h2>当前的n值:{{n}}</h2>
<button @click="n++">点击n++</button>
<div v-if="n%3 ===1">Angular</div>
<div v-if="n%3 ===2">React</div>
<div v-if="n%3 ===0">Vue</div>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
n:0
}
})
</script>1
2
3
4
5
6<!--v-if与template配合使用-->
<template v-if="n === 1 ">
<h2>miketaylorjuly123.cn</h2>
<h2>张加林</h2>
<h2>20岁</h2>
</template>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29<body>
<!--准备一个容器-->
<div id="root">
<ul>
<li v-for="p in persons">{{p}}</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
persons: [{
id: '001',
name: '张三',
age: 18
}, {
id: '002',
name: '李四',
age: 19
}, {
id: '001',
name: '王五',
age: 20
}]
}
})
</script>1
2
3<ul>
<li v-for="p in persons">{{p.name}}--{{p.age}}</li>
</ul>1
2
3
4
5
6
7<ul>
<li v-for="(a,b,c) in persons" :key="a.id">
<!--a,b in persons也可以,但是最好加()-->
<!--(a,b) of persons也支持-->
{{a}}---------{{b}}---------{{c}}
</li>
</ul>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<body>
<!--准备一个容器-->
<div id="root">
<ul>
<li v-for="(value,key) in car">
{{value}} ---------- {{key}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data:{
car:{
name: '迈巴赫',
price: '800W',
color: '深蓝'
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<body>
<!--准备一个容器-->
<div id="root">
<ul>
<li v-for="(char,index) in str">
{{char}}----------{{index}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
str: 'miketaylorjuly123.cn'
}
})
</script>1
2
3
4
5
6
7
8
9
10<body>
<!--准备一个容器-->
<div id="root">
<ul>
<li v-for="(number,index) in 6">
{{number}}-------{{index}}
</li>
</ul>
</div>
</body>1
2
3
4
5<ul>
<li v-for="(p,index) in persons" :key="p.id">
{{p}}-------{{p.age}}
</li>
</ul>1
2
3
4
5<ul>
<li v-for="(p,index) in persons" :a="p.id">
{{p}}-------{{p.age}}
</li>
</ul>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42<body>
<!--准备一个容器-->
<div id="root">
<ul>
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}} <input type="text">
</li>
</ul>
<button @click.once="add">添加人员</button>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
persons: [{
id: '001',
name: '张三',
age: 18
}, {
id: '002',
name: '李四',
age: 19
}, {
id: '003',
name: '王五',
age: 20
}]
},
methods:{
add(){
const p = {
id:"004",
name:'张加林',
age:20
};
this.persons.unshift(p);
}
},
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39<body>
<!--准备一个容器-->
<div id="root">
<input type="text" v-model="keywords" placeholder="输入关键词">
<ul>
<li v-for="(p,index) in filpersons" :key="index">
{{p.name}}-----{{p.age}}---------{{p.gender}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
keywords: '',
persons: [
{ id: '001', name: '马冬梅', age: 20, gender: '女' },
{ id: '002', name: '周冬雨', age: 28, gender: '女' },
{ id: '003', name: '周杰伦', age: 40, gender: '男' },
{ id: '004', name: '温兆伦', age: 50, gender: '男' }],
filpersons: []
},
watch: {
keywords: {
handler(newValue) {
immediate: true;
this.filpersons = this.persons.filter((p) => {
// 函数体
// return 过滤条件
console.log(newValue);
return p.name.indexOf(newValue) !== -1;
});
}
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33<body>
<!--准备一个容器-->
<div id="root">
<input type="text" v-model="keywords" placeholder="输入关键词">
<ul>
<li v-for="(p,index) in filpersons" :key="index">
{{p.name}}-----{{p.age}}---------{{p.gender}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
keywords: '',
persons: [
{ id: '001', name: '马冬梅', age: 20, gender: '女' },
{ id: '002', name: '周冬雨', age: 28, gender: '女' },
{ id: '003', name: '周杰伦', age: 40, gender: '男' },
{ id: '004', name: '温兆伦', age: 50, gender: '男' }],
},
computed: {
filpersons() {
return this.persons.filter((p) => {
console.log(this.keywords);
return p.name.indexOf(this.keywords) !== -1;
});
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45<body>
<!--准备一个容器-->
<div id="root">
<input type="text" v-model="keywords" placeholder="输入关键词">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="(p,index) in filpersons" :key="p.id">
{{p.name}}-----{{p.age}}---------{{p.gender}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
keywords: '',
sortType: '', // 0-原顺序,1-降序,2-升序
persons: [
{ id: '001', name: '马冬梅', age: 34, gender: '女' },
{ id: '002', name: '周冬雨', age: 28, gender: '女' },
{ id: '003', name: '周杰伦', age: 40, gender: '男' },
{ id: '004', name: '温兆伦', age: 50, gender: '男' }],
},
computed: {
filpersons() {
const arr = this.persons.filter((p) => {
console.log(this.keywords);
return p.name.indexOf(this.keywords) !== -1;
});
// 判断是否需要排序
if (this.sortType) {
arr.sort((p1, p2) => {
// 这里p1、p2是数组中的元素——对象
return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
})
}
return arr;
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31<body>
<!--准备一个容器-->
<div id="root">
<button @click="updateMei">更新马冬梅</button>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-----{{p.age}}---------{{p.gender}}
</li>
</ul>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
persons: [
{ id: '001', name: '马冬梅', age: 34, gender: '女' },
{ id: '002', name: '周冬雨', age: 28, gender: '女' },
{ id: '003', name: '周杰伦', age: 40, gender: '男' },
{ id: '004', name: '温兆伦', age: 50, gender: '男' }],
},
methods:{
updateMei(){
this.persons[0].name = '马老师'; // 奏效
this.persons[0].age=50; // 奏效
this.persons[0].gender = '男'; // 奏效
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14<script>
let data = {
name: '张加林',
site: 'miketaylorjuly123.cn'
};
let tmp = '张加林';
setInterval(()=>{
if(data.name !== tmp){
tmp = data.name
console.log('name被修改');
}
},100)
// 定时器开死,不可能这样实现
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<script>
let data = {
name: '张加林',
site: 'miketaylorjuly123.cn'
};
// 创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Observer(data);
console.log(obs);
// 准备一个vm实例对象
let vm = {};
vm._data = data = obs;
// 能接收一个对象为参数,创建一个监视的实例对象
function Observer(obj) {
// 汇总对象中所有的属性,形成一个数组
const keys = Object.keys(obj);
// 遍历
keys.forEach(((k)=>{
Object.defineProperty(this,k,{
get(){
return obj[k];
},
set(val){
console.log(`${k}被更改了,接下来将解析模板,生成虚拟DOM,……`);
obj[k] = val;
}
})
}))
}
</script>1
vm.gender = '男'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
collage:'UESTC',
student: {
name: '张加林',
site: 'miketaylorjuly123.cn',
age:20,
friends: [
{name:'jerry',age:20},
{name:'mike',age:21},
{name:'tony',age:30}
]
}
},
methods:{
addGender(){
// Vue.set(this.student,'gender','男');
this.$set(this.student,'gender','男');
}
}
})
</script>1
this.persons.splice(0,1,{id:'001',name:'马老师',gender:'男'})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69<body>
<!--准备一个容器-->
<div id="root">
<h2>学生信息</h2>
<h3>姓名:{{student.name}}</h3>
<h3>年龄:{{student.age}}</h3><button @click="student.age++">年龄++</button>
<h2 v-if="student.gender">性别:{{student.gender}}</h2>
<button @click="addGender">添加性别,默认为男</button>
<button @click="student.gender = '未知'">修改性别</button>
<h2>爱好</h2>
<ul>
<li v-for="(h,index) in student.hobby" :key="index">{{h}}</li>
</ul>
<button @click="addHobby">添加爱好</button>
<button @click="updateHobby">更新爱好</button>
<button @click="removeHobby">过滤爱好</button>
<ul>
<li v-for="f,index in student.friends" :key="index">{{f.name}}------{{f.age}}</li>
</ul>
<button @click="addFridens">添加朋友</button>
<button @click="updateFriends">修改朋友</button>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
collage: 'UESTC',
student: {
name: '张加林',
site: 'miketaylorjuly123.cn',
age: 20,
friends: [
{ name: 'jerry', age: 20 },
{ name: 'mike', age: 21 },
{ name: 'tony', age: 30 }
],
hobby:['打游戏','看番','睡觉']
}
},
methods: {
addGender() {
// Vue.set(this.student,'gender','男');
this.$set(this.student, 'gender', '男');
},
addFridens(){
this.student.friends.push({name:'wzith',age:12})
},
updateFriends(){
this.student.friends[0].name = '张三'; //注意:这是对象,有setter和getter
this.student.friends[0].age = 13;
},
addHobby(){
this.student.hobby.push('吃甜品')
},
updateHobby(){
this.student.hobby.splice(0,1,'看美剧')
// Vue.set(this.student.hobby,0,'看美剧');
},
removeHobby(){
this.student.hobby = this.student.hobby.filter((h)=>{
return h !== '打游戏'
})
}
}
})
</script>1
{"account":"111","password":"","gender":"female","hobby":["game"],"city":"ShenZhen","other":"111","agree":true}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64<body>
<!--准备一个容器-->
<div id="root">
<form @submit.prevent="demo">
<h2>输入框</h2>
<label for="account">账号:<input type="text" id="account" v-model="userInfo.account"></label><br />
<label for="password">密码:<input type="password" id="password" v-model="userInfo.password"></label><br />
年龄:<input type="text" v-model.number="userInfo.age">
<h2>单选框</h2>
性别:
<!-- radio要求亲自配置value -->
男<input type="radio" name="gender" v-model="userInfo.gender" value="male">
女<input type="radio" name="gender" v-model="userInfo.gender" value="female"><br />
<h2>多选框</h2>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
吃甜品<input type="checkbox" v-model="userInfo.hobby" value="sweet"> <br />
<h2>下拉框</h2>
所属校区:
<select v-model="userInfo.city">
<option value="">请选择校区</option>
<option value="BeiJing">北京</option>
<option value="ShangHai">上海</option>
<option value="ShenZhen">深圳</option>
<option value="GuangZhou">广州</option>
<br /><br />
</select>
<h2>其他信息</h2>
<textarea v-model.lazy="userInfo.other"></textarea>
<br />
<input type="checkbox" v-model="userInfo.agree">
阅读并接受<a href="miketaylorjuly123.cn">《用户协议》</a>
<br />
<button>提交</button>
</form>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
userInfo: {
account: '',
password: '',
gender: 'female', // 默认选female
hobby: [],
city: 'BeiJing',
other: '',
agree: '',
age: ''
}
},
methods: {
demo() {
console.log(this.userInfo)
// console.log(JSON.stringify(this._data))
}
}
})
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<body>
<!--准备一个容器-->
<div id="root">
<h2>显示格式化后的时间</h2>
<h3>现在是:{{fmtTime}}</h3>
</div>
</body>
<script>
Vue.config.productionTip = false;// 阻止VUE启动时生成生产提示。
new Vue({
el: '#root',
data: {
time: 1630671767228, //时间戳
},
computed: {
fmtTime() {
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss'); //给参数格式化参数时间,不给参数默认格式化当前时间
}
}
})
</script>
多个过滤器可以实现串联,过滤是按管道书写顺序来的。
局部过滤器:只有当前Vue实例能够使用,如果再出现一个Vue实例,就不能够使用了,即:如果vmA创建过滤器demoA,vmB创建过滤器demoB,则只能vmA用demoA,vmB用demoB。(以后一个vm,多个组件)
注意:
过滤器不但能用在插值语法中,还能用于数据绑定时的过滤:
但是只能用于v-bind,不能用于v-model
代码
1 |
|
总结
- 过滤器:
- 语法:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑处理)
- 语法:
- 注册过滤器:
Vue.filter(name,callback)
或new Vue(filters:{})
- 使用过滤器:
{{xxx | 过滤器名}}
或·v-bind:属性 = "xxx | 过滤器名"
- 注册过滤器:
- 备注:
- 过滤器也可以接收额外的参数,多个过滤器可以串联
- 并没有改变原来的数据,是产生新的对应的数据
1.26 Vue内置指令
v-text
作用:向其所在节点中渲染文本内容。
- 与插值语法的区别:
- v-text会拿到v-text中的变量值,然后替换整个节点中的值,而插值语法不会。
- 更加常用的是插值语法,因为它灵活。
- v-text会拿到v-text中的变量值,然后替换整个节点中的值,而插值语法不会。
v-text不能解析标签,而是将所有字符当做正常文本解析,不会当作标签结果:
1 |
|
v-html
v-html支持结构解析,而v-text不支持。
cookie
登录网易邮箱为例:
换一个浏览器,将Cookie要登录的页面的cookie全部删除,替换为已经登录的浏览器的Cookie中的key value,你就可以成功登录页面!
使用上述插件可以一键导入导出cookie。
安全问题
js获取cookie
1 |
|
点击后,获取当前正在所处网站的全部cookie,然后跳走,并且把所有的cookie以参数的形式传给坏人的服务器。
设置HttpOnly,使得cookie的该字段只能由HTTP协议可以读取,可以携带(js代码无法再直接读取cookie),所以敏感数据最好加HttpOnly限制。
总结
- v-html
- 作用:向指定节点渲染包含html结构的内容
- 与插值语法的区别:
- v-html会替换掉节点中所有的内容,而不会这样
- v-html可以识别html结构
- 特别要注意:v-html有安全性问题!!!
- 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击(跨站脚本攻击(XSS),是最普遍的Web应用安全漏洞,能够使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的。)
- 一定要在信任的内容上使用v-html,永远不要用在用户提交的内容上!!!
v-cloak
Win + R
=> cmd
=> node server
启动
访问链接:https://localhost:8080/resource/5s/vue.js
5s代表5s后返回vue.js给访问方。
虽然下述方式可以调节网速,但是无法控制外部的js返回时间。
js阻塞:JS具有阻塞特性,当浏览器在执行js代码时,不能同时做其它事情,即