起因
近期准备换工作,面试到一家公司,问我是否有写博客的习惯。细想来开发多年,并没有养成写技术博客的习惯,正好最近为了面试也在复习整理知识点。就先从解析知识点开始,养成写技术博客的习惯。由于这几年大部分都在使用vue全家桶进行开发,所以先从vue开始整理吧。准备后续将基础知识体系整理一下。当然,这里仅仅做一个梳理,肯定不可能写的多么的详细。整理完后,准备写一些进阶的技术博客。这里先从VUE2.X开始
一.MVVM
Model-View-ViewModel的缩写。一些原理后续统一整理,先整理知识点,功能点。
- Model(数据模型):用来处理业务逻辑和与数据库交互。在VUE中对应的就是data中的数据。
- View(视图):视图展示。在VUE中对应的就是模板代码。
- ViewMode(视图模型):用来处理Model层和View层的交互,实现数据绑定。在VUE中对应的就是VUE实例。原理是数据劫持(VUE2使用的是Object.defineProperty,VUE3使用的是Proxy,具体原理后续更新)
二.VUE实例
这里先不用脚手架。我们使用传统的html页面引入js的方式。下载vue.js文件(vue2)并引用。
在html中定义一个div,id设置为app用于绑定el。在script中创建vue实例,el绑定上定义的div,写一个data并定义变量。
注意在没有组件的情况下,我们data可以写成data:{}形式,而今后涉及的组件我们需要写成data(){return{}}形式。否则组件的数据做不到独立,会相互影响。况且编译也通不过。
<!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>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h1>hello,{{title}}</h1> //插值语法
</div>
<script type="text/javascript">
new Vue({
el:"#app",//绑定容器
data() {
return {
title:"VUE",
}
},
})
</script>
</body>
</html>
三.插值语法
{{js表达式}}。插值语法可以读取data中的变量,将文本渲染到页面上。可以使用js表达式。(js表达式本质上返回的也是一个值)
<div id="app">
<h1>hello,{{title + "2"}}</h1>
</div>
四.指令
VUE有很多的指令。都是以v-XXX的形式。包括v-once,v-show,v-if,v-else,v-else-if,v-for,v-html,v-text,v-bind,v-on,v-model指令。
4.1v-bind指令
v-bind主要作用就是为标签属性绑定变量,实现数据绑定。在容器中写上
<div id="app">
<h1>hello,{{title + "2"}}</h1>
<a v-bind:href="jumpUrl">{{jumpUrl}}</a> //jumpUrl是data 中定义的变量
</div>
在data中定义变量jumpUrl
data() {
return {
title:"VUE",
jumpUrl:"https://www.baidu.com/"
}
},
这样就实现了一个数据的绑定,当data中的jumpUrl改变,a标签的链接地址也改变。
v-bind可以简写成:
<a :href="jumpUrl"></a>
4.2v-on指令
4.2.1基本使用
v-on指令用于绑定事件监听。比如v-on:click=”方法名“就是绑定点击事件,v-on:mousemove=”方法名“绑定鼠标移入事件等等。
简写是@XXX,比如@click,@mousemove
<button v-on:click="changeUrl">改变URL</button>
等同于
<button @click="changeUrl">改变URL</button>
在vue实例中和data同一等级加上method:{},用于定义方法。注意定义的方法中的this指向的是vm实例,this.取的就是data中的数据。所以不能使用箭头函数 ,否则取不到值。
new Vue({
el: "#demo",
data() {
return {
title: "VUE",
jumpUrl: "https://www.baidu.com/",
};
},
methods: {
changeUrl() {
this.jumpUrl = "https://www.csdn.net/"
},
},
});
这样当我们点击改变URL时 a标签的文本和href都会改变
4.2.2使用 event
当我们的方法没有其他参数接收的时候,默认接收一个event对象,可以不用传,直接在方法中接收就行。
changeUrl(event) {
event.target.style.color = "red" //按钮的文本颜色变成了红色
this.jumpUrl = "https://www.csdn.net/"
},
如果我们的方法有参数,那么需要加上$event传递event
<button v-on:click="changeUrl('https://www.csdn.net/',$event)">改变URL</button>
changeUrl(newURL,e) {
e.target.style.color = "red"
this.jumpUrl = newURL
},
4.2.3事件修饰符
常用事件修饰符包括
- prevent:阻止默认事件
- stop:阻止事件冒泡
- once:事件只触发一次
- capture:使用事件的捕获模式
- self:只有event.target是当前操作的元素时才触发事件
1.prevent
<a v-bind:href="jumpUrl" @click.prevent="noJump">{{jumpUrl}}</a>
noJump(){
console.log("不跳转");
}
这样a标签的默认跳转行为就被阻止了
2.stop
如果不加上stop会冒泡。
<div @click="showFather">
<button @click="showSon">点我</button>
</div>
showFather(){
console.log("我是父亲");
},
showSon(){
console.log("我是儿子");
}
输出:我是儿子,我是父亲
加上stop
<div @click="showFather">
<button @click.stop="showSon">点我</button>
</div>
输出:我是儿子
3.once
<button @click.once="onceLog">一次性按钮</button>
onceLog(){
console.log("我只调用一次");
}
4.capture
将刚才.stop修饰符的代码改成
<div @click.capture="showFather">
<button @click="showSon">点我</button>
</div>
点击点我我们会发现打印的是 我是父亲 我是儿子
也就是说 从外往里捕获。而冒泡则是从内往外冒泡
5.self
self的意思是,忽略了事件冒泡和事件捕获的影响。只有直接作用在该元素上的事件才会被调用。并不是阻止冒泡或者捕获。简言之就是只有点击和self绑定的一致才触发。
<div id="box1" @click="showMsg">
box1
<div id="box2" @click.self="showMsg">
box2
<div id="box3" @click="showMsg">
box3
<div id="box4" @click="showMsg">box4</div>
</div>
</div>
</div>
样式
div {
width: 100px;
}
#box1 {
background: pink;
}
#box2 {
background: blue;
}
#box3 {
background: yellow;
}
#box4 {
background: green;
}
方法
showMsg() {
console.log(event.currentTarget.id);
},
我们会发现只有当点击box2的时候,才会打印box2并冒泡。点击其他的无论是冒泡还是捕获,都不会触发打印box2
连写
修饰符可以连写 @click.prevent.stop
注意.stop.self和.self.stop的区别:
@click.stop.self 自身的冒泡捕获阻止,也阻止了相邻的冒泡捕获继续传播。
@click.self.stop 只阻止自身的。
4.2.4键盘事件
1.使用按键的别名
使用: @keydown.键盘键别名 = “方法” 或者 @keyup
<input type="text" placeholder="按下回车" @keydown.enter="downKeys">
downKeys(){
console.log("我按下了回车");
}
常用的键盘别名
- 回车 enter
- 删除 delete
- 退出 esc
- 空格 space
- 换行 tab
- 上 up
- 下 down
- 左 left
- 右 right
没有提供别名 了直接用原始的key值
<input type="text" placeholder="按下Q" @keydown.Q="downKeys">
系统修饰键 ctrl、alt、shift、win
如果使用keyup ,那么需要按下其他键,再将其他键松开才触发
比如@keyup.Ctrl 在按下Ctrl没有反应,抬起Ctrl还是没有反应。但按下Ctrl,在按下V(任意)键,再抬起V,就触发了。
keydown不受影响
keyCode
使用keyCode码
<input type="text" placeholder="按下回车" @keydown.13="downKeys">
不建议使用,VUE3已经废弃
自定义
在vue实例中写
Vue.config.keyCodes.huiche = 13
<input type="text" placeholder="按下回车" @keydown.huiche="downKeys">
同样vue3已经废弃
4.3v-model
双向数据绑定,用于可输入的元素
<input type="text" v-model="name">
<h1>{{name}}</h1>
原理后面再整理
4.4v-if和v-show
都能表示显示和影藏。
注意v-if和v-show的区别。
v-show相当于加了display 只控制显示影藏,元素还在结构中。
v-if则直接将元素在结构中添加,删除。
如果切换频繁的元素,则用v-show,反之用v-if。
<h1 v-if="isShow">if</h1>
<h1 v-show="isShow">show</h1>
<button @click="isShow = !isShow">点击</button>
data(){
return {
isShow:true
}
}
v-if还能和v-else-if 以及 v-else 一起用。v-show不行。
注意结构必须在一起 中间 不能隔开。
<h1 v-if="n === 0">0</h1>
<h1 v-else-if="n === 1">1</h1>
<h1 v-else>other</h1>
<button @click="n++">+</button>
data(){
return {
n:0
}
}
4.5 v-for
循环渲染
<ul>
<li v-for="(item,index) in person" :key="item.id">
<span>index - {{index}},id - {{item.id}},name - {{item.name}}</span>
<input placeholder="请输入年龄" type="text" />
</li>
</ul>
data() {
return {
person:[
{
id:"1",
name:"张三"
},
{
id:"2",
name:"李四"
},
],
};
},
特别特别注意 key 需要是一个唯一的 不随数组变化而变化的值。所以不建议使用index。
因为如果在数组头部添加数据,index会改变。举个例子,将key改成index,加一个按钮。
<ul>
<li v-for="(item,index) in person" :key="index">
<span>index - {{index}},id - {{item.id}},name - {{item.name}}</span>
<input placeholder="请输入年龄" type="text" />
</li>
</ul>
<button @click="addPerson">加一个人</button>
methods: {
addPerson() {
let wangwu = {
id: "3",
name: "王五"
};
this.person.unshift(wangwu)
},
},
将年龄填上
点击按钮 就会发现数据不对了。因为原来张三的index是1,现在王五的index变成了1。
4.6v-once
意思是初次渲染时候显示,今后数据改变也不会改变
<h1 v-once>我是个不变的值:{{n}}</h1>
<button @click="n++">+</button>
点击button不会改变n的值
4.7v-text
渲染文本内容。区别在于
v-text会替换掉节点中的内容,插值语法不会。
<div v-text="str"></div>
data:{
str:'<h3>你好,VUE</h3>'
}
4.8v-html
渲染文本内容。区别在于
v-html会可以识别html结构,v-text不会。
<div v-html="str"></div>
data:{
str:'<h3>你好,VUE</h3>'
}
但是强烈不建议使用,千万注意永远不要用于用户提交的内容上面,会很容易被XSS攻击的。举个例子(PS:记得几年前有次面试问过我类似问题)
<input v-model="inputData" type="text" />
<div v-html="inputData"></div>
data:{
inputData: null,
}
然后再输入框内将下面这段复制进去
<a href="javascript:alert(document.location.href)">点击抽奖</a>
点击 点击超链接(只是举个例子,没有什么攻击,放心点击)
弹出来的就是href信息。
如果这个超链接跳转到其他的服务器并且带上的数据是document.cookie或者其他信息,那么用户名,密码就有被窃取的可能。所以用v-html的时候要非常慎重。
4.9 v-cloak
解决屏幕闪动的。可以解决网速慢时页面展示出{{xxx}}的问题。
需要服务器支持,不太好演示,这里只写用法。v-cloak没有值,直接用
<div v-cloak="str"></div>
4.10 v-pre
跳过当前编译。简单说就是 当前代码不编译,是什么就是什么。
<h1 v-pre>{{n}}</h1>
<h1 >{{n}}</h1>
<button @click="n++">+</button>
4.11自定义指令
全局自定义
在new Vue({}) 之外添加
Vue.directive('focus',{
//指令与元素成功绑定时
bind(element,binding){
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
}
})
<input type="text" v-focus>
局部指令
在和data平级添加
directives:{
setcolor(element,binding){
element.style.color = binding.value
},
}
<h1 v-setcolor="red">您好</h1>
时间有限,先整理这么多吧。等空了再继续整理。有什么错误或者不足的地方,望大佬指正。争取从VUE的基础知识点开始整理,然后高阶知识点,VUE2原理,VUE3,VUE3原理这么个顺序整理吧,如果这些到时候都完了,再整理些其他的。