思维导图
Vue:千锋Vue | ProcessOn免费在线作图,在线流程图,在线思维导图
Vue基础
Vue 用于构建用户界面的 MVVM的 渐进式框架
Vue特点
-
MVVM
-
M 数据
-
V 视图
-
VM
数据改变 视图自动刷新 (通过VM来刷新 new Vue 返回实例)
-
-
渐进式
核心库:体积很小(没有把所有的功能都挂载到 核心库上面)
插件:通过插件的形式,将插件所携带的功能挂载到 Vue上
-
声明式
-
声明式(告诉计算机,想要什么,怎么做我不管)
-
命令式(将程序中需要运行的每一个 指令 一步一步告诉计算机去运行)
-
-
组件化
Vue雏形
const vm = new Vue({
el: '#app' // element缩写 挂载实例 #app元素 内部可以使用Vue代码
,data:{ // data属性 放组件数据的
message: 'Hello Vue'
}
,methods: { // 存放当前实例的方法
act() { // 注意 方法必须这样写
return 111
}
}
})
// 挂载实例除了可以通过el属性 还可以在外部挂载
const vm = new Vue({
data: {
msg: '你好 Vue'
}
}).$mount(document.querySelector('#app'))
// vm.$mount(document.querySelector('#app'))
模板语法
// { { }} 写在view中的 /* 语法 1. { {}}可以直接使用或者调用 实例的属性或方法 { {}}里面的变量或者方法调用 会自动去实例上找,如果实例上没有会报错 2. 内部是js环境 且 最好是表达式,{ {}} 写在视图中做视图渲染 如果调用方法,那么这个方法最好有返回值,否则不会渲染内容 (不能写if结构) 3. 关于全局的方法 Vue { {}}模板 创建了一个白名单, 白名单中的全局方法,是可以使用的 'Infinity,undefined,NaN,isFinite,isNaN,' 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' 'require' // for Webpack/Browserify 特点: - 大部分都是处理数据的 - 都有返回值 */
指令 directive
扩展了 标签(组件) 的 属性的功能
<组件 v-指令名="值" /> <!-- 注意:指令的值所在 引号中 是一个js的环境,且只能写表达式,不要写语句。 变量会 自动识别, 实例上的属性 或者方法。 全局的有 白名单 -->
v-model
将表单控件的value与一个变量 进行双向绑定
表单控件: 文本框、密码框、单选框、复选框、下拉列表、文本域...
v-text
将 元素的 文本内容 与data状态进行双向绑定
v-html
将内容解析成 html (慎重使用,一般后台返回富文本内容时使用)
v-bind:属性
(属性:是标签的普通属性 包括自定义属性)
将组件或标签的普通属性 变成 动态属性 (属性的值会和一个实例中的数据进行绑定)
语法糖::属性
v-on:事件
Vue 中 定义 元素的 事件, 事件函数 会与Vue实例上的方法进行绑定
语法糖:@事件
两种事件函数的绑定方式
// fn是事件函数,第一个参数就是事件对象 <button @click="fn">按钮</button> // fn不是事件函数,只不过按钮点击时 会触发 适用场景 需要自定义传参 <button @click="fn()">按钮</button> // 如果通过fn()方式绑定,如果需要事件对象,可以在调用时传入 `$event` <button @click="fn(a,b,$event)">按钮</button>
Vue事件修饰符
修饰 绑定事件的
-
@事件.修饰符
-
v-on:事件.修饰符
.stop // 单击阻止事件继续传播
.prevent // 提交页面不再重载页面
.capture // 捕获阶段触发
.self // 当前元素所绑定的事件只能由自己触发,后代无法触发
.once // 只执行一次
v-if 条件渲染
v-if // 有条件的渲染一个元素,条件为false时,此元素不再dom树(不渲染)
v-else // 必须是 v-if 所绑定元素的下一个兄弟元素,此时 当v-if条件为false时显示,
// 为true时消失 (相当于if...else...结构)
v-else-if // 多分支 注意,必须是连续地兄弟元素,且v-if是第一个兄弟,v-else是最后一个兄弟
v-show
控制元素显示消失状态
用法 同v-if
对比 v-if
相同点:都能改变元素的(显示、消失)切换状态,且值为true显示,false消失
不同点:
-
v-show
是改变元素的 display属性切换的,v-if
是直接移除元素 -
当初始值为false时,
v-if
所绑定的元素是 惰性的(不加载)
使用场景:
v-show
有更高的 切换性能 (频繁切换时使用v-show
)
v-if
当初始值为false时, 且不频繁切换使用 v-if
(初始为false不加载的)
v-for
列表渲染 循环
循环渲染
<ul>
<li v-for="item in arr">{
{item}}</li> // 普通的循环
</ul>
<hr>
<ul>
<li v-for="(item, index) in arr"> // 循环数组加下标
{
{index}}
=>
{
{item}}
</li>
</ul>
<hr>
<ul>
<li v-for="item in obj"> // 循环对象
{
{item}}
</li>
</ul>
<hr>
<ul>
<li v-for="(item, key) in obj"> // 循环对象加key
{
{key}}
=>
{
{item}}
</li>
</ul>
<hr>
<ul>
<li v-for="(item, key, index) in obj"> // 循环对象加key,index
{
{key}}
=>
{
{item}}
=>
{
{index}}
</li>
</ul>
const app = new Vue({
el: '#app'
,data:{
arr: ['蜘蛛精','玉兔精','黑熊怪','小旋风']
,obj:{
name: '小明'
,gender: '男'
,age: 18
}
}
})
每一个循环的元素 一定要加一个key属性 独一无二的key属性
<li v-for="(item,index) in items" key="index"> {
{ item }} </li>
循环中为什么要加key?
添加key的元素不参与复用,diff算法会逐层按key比较,加快了diff比较效率,加快了页面渲染效率。
Vue中的 :class
<div :class="a"></div> // 解析成box类
<div :class="[a,b,'box3']"></div> // 解析成box box2 box3
<div :class="{isActive:true}"></div>
<div :class="{isActive:c}"></div>
<div :class="{isActive:1==2}"></div>
// div是否有isActive类取决于对象的值是否为真
<div :class="[a,b,'box3',{isActive:1==2}]"></div> // 可以嵌套
{
data:{
a:"box",
b:"box2",
c
}
}
Vue中的 :style
<body>
<div id='app'>
<div :style="{width:100*3+'px',height:200+'px',backgroundColor:'red'}"></div>
<div :style="{width:100*3+'px',height:200+'px',backgroundColor:isRed?'red':'blue'}"></div>
</div>
<script src='https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js'></script>
<script>
const app = new Vue({
el: '#app'
,data:{
isRed: false
}
})
</script>
</body>
增加了 :style对象的写法
好处:
-
值 是js的环境,里面除了语句之外,还可以写js的表达式,可以计算属性
MVVM的原理
VUE 2.X MVVM 底层API
Object.defineProperty()
MVVM原理:
当我们 new 一个 Vue 实例时,都会传入一个data属性(属性的值是对象),data保存了我们当前实例的数组(mvvm中的m),new的时候,Vue会遍历 data对象中的所有属性,且通过Object.defineproperty,将data中的每一个属性都转换了一个 getter
/setter
,这样之后我们data对象中所有的数据都是可追踪的。
每一个组件(实例),都有一个watcher(观察者),检测这个组件(实例)中所有的 getter/setter
只要其中一个触发,观察者就 调用 render函数 生成虚拟DOM, 会跟上一次存储在内存中的虚拟DOM进行比较(diff算法),得到代价最小的一种方案,更新真实DOM。
(每一次渲染真实DOM后,都会将对应虚拟DOM保存在内存中,方便进行比较)
虚拟DOM:
虚拟DOM是什么?
用js对象的结构,去描述一段真实的DOM树。
在更新真实DOM之前,先比较虚拟DOM(diff),然后尽量减少DOM操作。
MVVM中的一些问题
Vue监测不到没有data初始化的数据
-
一个数据没有在data中初始化定义,而是后期动态添加的,Vue是监测不到它的变化的,数据改变后不会自动刷新。
要求:使用到的数据一定要在data中初始化。
定义不同类型的数据的时候,初始值有一定的要求
Number:0/-1(如果代表下标)
字符串:“”
对象:null / {}
数组:[]
defineProperty
捕获不到 数组的某些操作
哪些操作:
-
数组[下标] = 值
-
直接改变数组的length
删除 使用 数组.splice(从哪删, 删几个[, ...添加的元素])
解决方案:
改变数组,通过一个方法来改变
this.$set(对象, 属性, 值)
this.$set(数组, 下标, 值)
nextTick()
解决数据更新,DOM更新异步的问题
当我们的数据改变后,视图刷新(调用render生成虚拟DOM