🎾 Vue基本概念
Vue介绍
- Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的是一个渐进式的javascript框架
- vue 中文网
- Vue.js 是什么
什么是渐进式?
渐进式: 逐渐进行 逐渐增强。
vue不会强制要求项目中完全都有vue来实现。
什么是框架?
- jquery: jquery是一个js库(Library)
- js库:一系列方法的集合。js库不会提供逻辑,逻辑由程序员自己控制。
- vue: vue是要给js框架(framework)
- js框架: 一整套完整解决方案, 大部分的逻辑框架已经确定好了,我们只需要在框架中填充自己的代码,完形填空
库和框架的概念
Library
库,本质上是一些函数的集合。每次调用函数,实现一个特定的功能
- 代表:jQuery
- 使用库的时候,把库当成工具使用,需要自己控制代码的执行逻辑。
Framework
框架,是一套完整的解决方案,使用框架的时候,需要把你的代码放到框架合适的地方,框架会在合适的时机调用你的代码
- 框架规定了自己的编程方式,是一套完整的解决方案
- 使用框架的时候,由框架控制一切,我们只需要按照规则写代码
库和框架的区别
- 使用库的时候,很自由,只要调用库提供的各种各样的方法就行,也可以不用其他的一些方法
- 使用框架的时候,需要按照框架的规则写代码,限制会非常多,但同时框架的功能也很强大,可以极大的提升开发的效率。
MVVM的概念
参考资料:从Script到Code Blocks、Code Behind到MVC、MVP、MVVM
MVC
- MVC是一种软件架构模式,也有人叫做设计模式,最早出现在后端
- M: Model 数据模型(专门用来操作数据,数据的CRUD)
- V:View 视图(对于前端来说,就是页面)
- C:Controller 控制器(是视图和数据模型沟通的桥梁,用于处理业务逻辑)
MVVM
MVVM,一种更好的UI模式解决方案
- M:model数据模型(ajax获取到的数据)
- V:view视图(页面)
- VM:ViewModel 视图模型
MVC vs MVVM
- MVC模式,将应用程序划分为三大部分,实现了职责分离,需要自己实现controller的代码,需要操作DOM
- MVVM通过
数据双向绑定
让数据自动地双向同步- V(修改视图) -> M(数据自动同步)
- M(修改数据) -> V(视图自动徒步)
Vue中的MVVM
虽然没有完全遵循 MVVM 模型,Vue 的设计无疑受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的简称) 这个变量名表示 Vue 实例
注意:
1. 在vue中,不推荐直接手动操作DOM!!!
2. 在vue中,通过数据驱动视图,不要在想着怎么操作DOM,而是想着如何操作数据!!
🏀 Vue初体验
基本使用步骤
安装 下载vue
npm install vue
注意:开发期间使用未压缩版vue.js!!!重说三
引入一个vue文件
引入了vue.js文件后,vue.js文件会暴漏一个全局的Vue构造函数
- 创建vue实例
- 初始化一个vue实例, 需要指定 视图 数据
- 使用vue的时候,我们需要关注两个东西
- el: element: 缩写 指定vue管理的视图, 某个盒子的选择器
- data 指定vue中使用的数据
<div id="app">
<!-- 3.可以通过{{}}显示vue中的数据 -->
<h1>{{msg}}</h1>
</div>
<!-- 1. 引入vue.js -->
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
// 2. 创建vue实例,需要指定el和data属性
const vm = new Vue({
// 指定vue监管的视图区域,只要id为app的div内部才会受vue的管理
el: '#app',
// 提供了vue中使用的数据
data: {
msg: 'hello vue'
}
})
</script>
问题1:把{{msg}}
写到div#app
外能生效么?
问题2:el能否写成ele, data能否写成datas? 框架的限制很多,但是习惯就好了!
使用Vue的注意事项
- new vue() Vue是一个构造函数首字母大写
- el不能指定为body或者html, 应该是一个div
- 如果想要修改页面中的内容,应该怎么办, data中所有的数据都添加给了vm对象
可以通过vm.xxx 进行修改
插值表达式
插值表达式:
{{}}
,也叫Mustache语法,小胡子语法,因为长得像胡子- 作用:可以在视图中显示data中的数据,也就是从
data
中获取数据,并展示在模板中 - 说明:
{{}}
中只能出现JavaScript表达式 - 说明:数据对象的属性值发生了改变,插值处的内容都会更新
- 作用:可以在视图中显示data中的数据,也就是从
vue中插值表达式的语法
{{msg}}
{{car.brand}}
{{car.price + 100}}
{{三元运算符}}
vue中插值表达式的注意点
- {{}}中使用的数据必须在data中存在
- {{}} 虽然能够使用表达式,不能出现js的语句,不能在{{}}中写if for等关键字
- {{}} 不能在属性中使用 ```html
Hello, {{ msg }}.
{{ isOk ? ‘yes’: ‘no’ }}
{{ 1 + 2 }}
<a name="e6fe3c9b"></a>
# 🏐 Vue指令
> 指令 (Directives) 是带有 `v-` 前缀的特殊属性,可以在html标签中使用,可以看成特殊的html属性
- 作用:指令提供了一些特殊的功能,当指向绑定到标签上时,可以给标签增加一些特殊的行为
- vue总共提供了14个指令 也可以自定义指令
<a name="3f860172"></a>
## v-bind指令
> v-bind指令 用于访问data中的数据,在标签的属性中使用
1. 为什么要用v-bind指令
插值表达式不能用在html的属性上,如果想要动态的设置html元素的属性,需要使用v-bind指令
2. v-bind如何使用
html
title=”title” v-bind:属性名=”属性的值”
:title :src
3. 注意事项
bind访问的值必须在data中存在的
<a name="c7e42502"></a>
## v-model指令
> 在表单元素上创建双向数据绑定,用于监听用户的输入事件以更新数据
1. v-model的作用是
1. 给表单元素使用
1. 创建双向数据绑定
2. v-model的语法是什么
html
v-model=”值”
3. v-model的注意事项
1. **只能表单元素使用**
1. 必须在data中存在
1. v-model会忽略掉原本的value值 checked
<a name="Fs7gG"></a>
### 使用场景
html
Message is: {{ message }}
```html
<p>{{desc}}</p>
<textarea cols="30" rows="10" v-model="desc"></textarea>
html
<p>{{city}}</p>
<select v-model="city">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">深圳</option>
</select>
html
<p>{{isCheck}}</p>
<input type="checkbox" v-model="isCheck">
### 双向数据绑定
1. 简单的说:当数据变了——-=> 视图会跟着变
视图变了 =======> 数据跟着变
2. 一般说:双向数据绑定将DOM与Vue实例的data数据绑定到一起,彼此之间相互影响
1. 数据的改变会引起DOM的改变
1. DOM的改变也会引起数据的变化
3. 怎么知道对象的某个数据发生了改变?
1. angularjs 1:脏数据检查机制 轮询 缺点: 性能比较低 兼容ie8
1. vue用的是数据劫持: 劫持data的msg属性 使用了ES5中的语法: Object.defineProperty(参数1:对象名, 参数2:属性名, 参数3:修饰一个对象)
注意:Object.defineProperty()
方法是ES5中提供的,IE8浏览器不支持这个方法。因此,Vue支持IE8及其以下版本浏览器4. 数据劫持的原理:监听文本框的事件,知道数据发生了改变,劫持这个数据,再更改数据,让视图跟着改变。
html
<script>
const data = {
msg: '哈哈'
}
const input = document.querySelector('input')
input.value = data.msg
// 核心原理:监听文本框的事件
input.addEventListener('input', function() {
data.msg = input.value
})
// 核心原理: 知道数据发生了改变,,,劫持这个数据
let temp = data.msg
//设置了Object.defineProperty中的get和set方法
//作用:指定读取或设置对象属性值的时候,执行的操作
Object.defineProperty(data, 'msg', {
get(){ //get方法会劫持 msg这个属性的获取操作
console.log('获取了值')
return temp
},
set(value) { // set方法会劫持到这个属性msg的设置操作
console.log('设置了值')
temp = value
// 应该让视图跟着改变
input.value = temp
}
})
</script>
相关
### Vue双向绑定的极简实现
html
<!-- 示例 -->
<input type="text" id="txt" />
<span id="msgBox"></span>
<script>
const txt = document.getElementById('txt')
const msgBox = document.getElementById('msgBox')
const obj = {}
// 给对象obj添加msg属性,并设置setter访问器
Object.defineProperty(obj, 'msg', {
// 设置 obj.msg 执行的操作
set: function (curVal) {
txt.value = curVal
msgBox.innerText = curVal
}
})
// 监听文本框的改变
txt.addEventListener('input', function (event) {
obj.msg = this.value
})
</script>
## v-on指令
> v-on是用来给元素注册绑定事件,绑定的事件从methods
中获取
### v-on的语法
html
v-on:事件名 = "事件函数"
v-on:click 可以简写成 @click
<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
### v-on的注意点
注册事件需要一个事件的函数创建vue实例的时候 ,data是用来给vue实例提供的属性(数据),不应该提供方法
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 1. 给翻转案例注册点击事件 -->
<button @click="reverse">翻转</button>
<p>{{msg}}</p>
</div>
<script src="vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
msg: 'hello vue!'
},
methods: {
// methods中的所有的方法内部的this都指向vm
// vue源码内部 reverse.bind(vm)
reverse() {
// 翻转msg
// js基础
// 1. 字符串没有reverse方法
// 2. 数组有reverse方法
// 3. 字符串有一个方法 split() 切割一个字符串变成数组
// 4. 数组有个reverse方法,可以翻转
// 5. 数组有个join方法,可以拼成字符串
// console.log(this.msg)
this.msg = this.msg.split('').reverse().join('')
}
}
})
</script>
</body>
</html>
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 注册事件 -->
<button @click="start">跑</button>
<button @click="stop">停</button>
<h1>{{msg}}</h1>
</div>
<script src="vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
msg: '小龙虾29.8一斤,买3斤送1斤!',
timeId: ''
},
methods: {
start() {
// clearInterval(this.timeId)
// 如果有定时器在跑,直接结束
if (this.timeId) {
return
}
// 开一个定时器, 每次都截取字符串的第一个字符串,放到最后一个字符
// 用了箭头函数后将不能指向this
this.timeId = setInterval(() => {
// console.log(this.msg)
this.msg = this.msg.slice(1) + this.msg.slice(0, 1)
}, 300)
},
stop() {
clearInterval(this.timeId)
// 把定时器的id清空
this.timeId = ''
}
}
})
</script>
</body>
</html>
html
() [] // + - : 前面的语句必须结束
var num= 11
;(function(){
console.log(22)
})()
console.log('哈哈')
console.log('呵呵')
html
"快速生成vue模版": {
// 配置简写
"prefix": "vue",
// 如果有一行,可以是字符串
// 如果是多行,需要是数组
"body": [
"<!DOCTYPE html>",
"<html lang=\"en\">",
" <head>",
" <meta charset=\"UTF-8\" />",
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />",
" <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\" />",
" <title>Document</title>",
" </head>",
" <body>",
" <div id=\"app\">",
" <h1>{{ msg }}</h1>",
" </div>",
"",
" <script src=\"vue.js\"></script>",
" <script>",
" const vm = new Vue({",
" el: '#app',",
" data: {",
" msg: 'hello vue'",
" }",
" })",
" </script>",
" </body>",
"</html>"
]
}
### 事件修饰符
注册事件经常需要阻止冒泡 阻止浏览器默认行为
html
@事件名.事件修饰符 = "事件函数"
- prevent 阻止默认行为 a标签 表单的提交
- stop 阻止冒泡
- capture 捕获阶段执行
- self 只有点击自己才执行,点击子元素不执行
- once 只会执行一次
### 按键修饰符
在监听键盘事件时,我们经常需要检查常见的键值。Vue 允许为 v-on
在监听键盘事件时添加按键修饰符:
- enter
- tab
- esc
- delete (捕获“删除”和“退格”键)
- space
- up
- down
- left
- right
javascript
@keyup.enter="fn"
## v-text指令
> 更新元素的 textContent属性
。如果要更新部分的 textContent
,需要使用 {{ Mustache }}
插值。
html
<h1 v-text="msg"></h1>
## v-html指令
> 更新DOM对象的 innerHTML,html标签会生效
html
<h1 v-html="msg"></h1>
注意:在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 **v-html**
,永不用在用户提交的内容上。
## v-show和v-if1. v-show:用于控制元素显示或者隐藏 1. v-show=”值” 如果这个值是true,表示显示 如果是false隐藏 1. v-show:通过样式 display属性控制显示和隐藏 2. v-if: 用于控制元素的显示和隐藏 1. v-if=”值” 如果这个值是true,表示显示 如果是false隐藏 1. v-if通过删除或者创建一个元素来控制显示和隐藏的 以后用哪个?????
如果一个盒子需要频繁的显示和隐藏,应该用 v-show
如果一个盒子要么显示要么隐藏,频率低 应该用 v-if 共同点:都能控制显示和隐藏
区别: v-show适合频繁切换 v-if适合要么显示要么隐藏
html
<p v-show="isShow">这个元素展示出来了吗???</p>
<p v-if="isShow">这个元素,在HTML结构中吗???</p>
## v-else与v-else-if指令
```html
欢迎你,尊贵的v7用户
你好,请登录
<h3 v-if="age >= 18">去酒吧</h3>
<h3 v-else-if="age >= 12">去网吧</h3>
<h3 v-else>去幼儿园</h3>
<a name="u15LK"></a>
## v-for
> v-for用于遍历一个数组或者一个对象,v-for是一个属性, v-for指令谁需要重复的渲染,就给谁加
<a name="lMNxW"></a>
### 两种用法
<br />
- 遍历数组
v-for="item in 数组" item表示每次遍历出来的值,item的名字是可以随意起<br /> v-for="(item,index) in 数组" item表示值 index:下标
- 遍历对象
v-for="value in 对象"<br /> v-for="(对象属性, 对象名) in 对象"
```html
<div id="app">
<h1>pp的爱好</h1>
<ul>
<li v-for="item in hobby">{{item}}</li>
</ul>
<ul>
<li v-for="(item,index) in hobby">{{index}}-----{{item}}</li>
</ul>
<ul>
<li v-for="index in hobby">{{index}}</li>
</ul>
<ul>
<li v-for="(v, k) in girlFriend">{{k}}------{{v}}</li>
</ul>
</div>
key属性
使用 key,VUE会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。为了让渲染更加高效。
推荐使用
**v-for**
的时候提供**key**
属性,能够根据“就地更新”策略提升列表渲染的性能使用v-for的时候一定要加key值 如果不加,默认采用就地更新原则,正常情况没有问题。
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
- 但是有时可以更加优化“就地更新”策略,加key
<ul>
<li v-for="item in list" :key="item">
<input type="checkbox">
{{item}}
</li>
</ul>
提升性能:v-pre
- 说明:跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
<span v-pre>{{ this will not be compiled }}</span>
提升性能:v-once
- 说明:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
<span v-once>This will never change: {{msg}}</span>
样式处理-class和style
- 使用方式:
v-bind:class="expression"
or:class="expression"
- 表达式的类型:字符串、数组、对象(重点)
- 语法:
<!-- 1 -->
<!-- 重点 -->
<div v-bind:class="{ active: true }"></div> ===>
<div class="active"></div>
<!-- 2 -->
<div :class="['active', 'text-danger']"></div> ===>
<div class="active text-danger"></div>
<!-- 3 -->
<div v-bind:class="[{ active: true }, errorClass]"></div> ===>
<div class="active text-danger"></div>
--- style ---
<!-- 1 -->
<div v-bind:style="{ color: activeColor, 'font-size': fontSize + 'px' }"></div>
<!-- 2 将多个 样式对象 应用到一个元素上-->
<!-- baseStyles 和 overridingStyles 都是对象 -->
<div v-bind:style="[baseStyles, overridingStyles]"></div>
案例:todomvc
计算属性
计算属性:当计算属性依赖的数据发生改变的时候,计算属性会重新计算一次,如果计算属性依赖的属性没有发生改变,那么计算属性就不会重新计算。
基本使用
var vm = new Vue({
el: '#app',
data: {
n1:'',
n2:''
},
//n3依赖与n1和n2的值,当n1 和 n2发生改变的时候,这个函数就会执行。
//返回值就是n3的值
computed: {
n3(){
return +this.n1 + +this.n2;
}
}
});
计算属性是基于它们的依赖项进行缓存的
如果页面中需要使用多次计算属性的值,只会计算一次,计算属性只有在它的相关依赖发生改变时才会重新求值。
计算属性不能与data中的属性同名,因为无论是data中的属性还是计算属性,最终都是挂载到vm上的