Vue是前端开发主流框架之一,对于开发者来说解决了好多细节问题,方便了开发,提高了效率,下面我就带来Vue2.0的一些基础的内容归纳总结,后期我会归纳Vue3.0的新变化
文章参考:
Vue基础概念
Vue教程
Vue视频教学
生命周期
Vue介绍
- Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架
- 它采用自底向上增量开发的设计,使得开发者只需关注视图层,易于上手,
- 还便于与第三方库或既有项目整合 通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件
Vue概念
渐进式框架:
- 渐进式是主张最少,不强主张,不做职责之外的事情,需要什么就使用什么。
- 一步一步往下走,而不是把所有的东西都用上。
- 比如客户端路由,构建工具等等都有自己的解决方案,它们之间相互独立,不需要全部整合在一起
自底向上逐层应用
就是先写好基础的东西再添加一些效果,逐层添加
MVVM
- MVVM是Model-View-ViewModel的缩写
- Model就是数据部分,也就是你写数据代码的区域,类似于JavaScript对象
- View就是视图部分,也就是DOM
- ViewModel是连接两者的枢纽,可以通过ViewModel来实现双方的通讯,
- 数据变化时,通过DataBingings它能够监听这种变化,及时反馈给视图并做出修改
- 视图变化时,也会通过DOM Listeners来监听并改变Model层的数据
- 这样就保证了视图和数据的一致性;从而实现双向数据绑定的功能
声明式渲染
就是Vue采用一个简洁的模板语法来声明式的将数据渲染进DOM系统
Vue下载和引入
- 我推荐使用npm;因为npm可以方便的和webpack打包工具配合;同时 Vue 也提供配套工具来开发单文件组件
- node环境下运行并输入指令
npm install vue
- 然后使用标签引入即可使用
初始化
- 需要一个vue实例 里面包含一个配置选项(配置项后面会详细学习)
var vm = new Vue({
el:"#app",
data:{},
methods:{}
})
- 需要一个容器,里面放置一些插值语法,也就是view渲染呈现的内容
<div id="root">
<h1>hello {{name}}</h1>
</div>
- 下面就开始往vue实例里面添加属性
var vm = new Vue({
el:"#app", //用于指定当前vue实例为哪个容器服务 值通常为css选择器选择器字符串
data:{
name:"啦啦啦", // 用于存储数据 且更换CSS选择器里面所选元素的内容 暂时写成一个对象为了方便多个数据更换
},
methods:{} //先暂时不写
})
运行页面会发现出现了 hello 啦啦啦的内容;简单的初入就完成了
如果你在控制台修改vm.name=‘妮妮’ 就会发现页面被修改了 成为 hello 妮妮
总结:
- 我们不再和 HTML 直接交互了,一个 Vue 应用会将其挂载到一个 DOM 元素上
- app容器里面代码依然符合html css 代码规范 只不过混入一些特殊的vue格式规范
- {{}} 此方法可以在 html 代码里使用vue 插值
模板语法
插值
- 文本插值
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值
<span>Message: {{ name }}</span>
<span v-once>这个值不会被改变{{age}}</span> // 添加了v-once表示整个值不会更新
- 原始HTML
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,可以使用 v-html 指令:
<p v-html="nei">我里面有html文本</p>
然后再配置项里面添加一写html结构
data: {
nei: "<p>我是内部的p</p>",
}
- 属性
Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind 指令
<span v-bind:id="dynameic">给我绑定了一个hello的id</span>
data:{
dynameic:"hello", //给上面span标签绑定一个id值
}
这时候span就多了一个值为hello的id
- JavaScript表达式
对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持;意味着你直接可以在{{}}里面编写js代码
{{ number + 1 }}
<span>{{ok?'yes':'no'}}</span>
指令
指令 (Directives) 是带有 v- 前缀的特殊 attribute
- v-if: 根据表达式的值的 truthiness 来有条件地渲染元素
<p v-if="seen">现在你看到我了</p>
这里,v-if 指令将根据表达式 seen 的值的真假来插入/移除 p元素
- v-else:v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
-
v-for:v-for 具有比 v-if 更高的优先级
-
v-on:它用于监听 DOM 事件;值得注意的是它的美称要写在方法配置项里
<div @click="click1">
<div @click.stop="click2">
click me
</div>
</div>
var app = new Vue({
el: "#app",
data: {},
methods: {
click1: function() {
console.log("click1___");
},
click2: function() {
console.log("click2__");
}
}
})
- v-bind:该指令可以用于响应式地更新 HTML attribute
<a v-bind:href="url">...</a>
在这里 href 是参数,告知 v-bind 指令将该元素的 href 属性值与表达式 url 的值绑定
计算属性和侦听器
计算属性
- 因为模板内表达式非常便利,但是太多的逻辑会让模板难以维护;对于复杂的逻辑,应当使用计算属性
- 它支持数据缓存,也就是页面重新渲染时,只有数据发生改变才会执行函数
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
结果:
Original message: “Hello”
Computed reversed message: “olleH”
如果我们修改vm里面的值,会发现vm.reversedMessage 的值始终取决于 vm.message 的值。
- 在computed中的,属性都有一个get和一个set方法。当 computed属性的属性值是函数,那么默认是get方法,函数的返回值就是属性的值;当数据变化时,调用set方法。
<div id="demo">{{ fullName }}</div>
<div id="demo">{{ fullName1() }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
},
methods:{
fullName1:function(){
return this.message.split('').reverse().join('')
}
}
})
现在再运行 vm.fullName = ‘John Doe’ 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新
同时你也会发现模板里面调用方法也能出现和计算属性一样的结果;但是两者有什么不同呢
- 使用
computed:定义的函数可以直接作为变量使用
methods:必须调用才能
- 缓存
computed里的数据会被缓存,每次更新都会先对比数据是否发生了变化,减少了渲染时间。
methods里的函数不会被缓存,只要数据有更新,就会执行对应的函数。
侦听器
- Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性
- 它可以侦听任何逻辑
- 不支持数据缓存;意味着页面重新渲染时,无论值变不变,都会重新执行
- 接收两个参数,新值和旧值
- 不要使用箭头函数(因为箭头函数没有 this,因此它的 this 会继承它的父级函数,但是它的父级函数是 window,导致箭头函数的this 指向 window,而不是 Vue 实例)
- 深度监视(deep:true 可以监视对象内部值发生的改变 多层)和普通监视(vue中的watch 默认不可以监视对象内部值发生的改变 只能监视一层)
- Vue 实例将会在实例化时调用$watch(),遍历 watch 对象的每一个属性
<div id="root">
<h3>今天天气很{{info}}</h3>
<!-- <button @click="isHot = !isHot">切换天气</button> -->
<button @click="changeWeather">切换天气</button>
</div>
var vm = new Vue({
el: '#root',
data: {
isHot: true,
},
watch: {
isHot: {
immediate: true, // 默认false 初始化时让handler调用一下
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
}
}
}
})
// 第二种写法 如果创建时还不知道要监视谁 后期通过用户需求进行监视就用这一种
vm.$watch('isHot', {
immediate: true, // 默认false 初始化时让handler调用一下
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
}
})
class和style的绑定
绑定HTML
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可
- 对象语法
上传单个字段值
<div v-bind:class="{ active: isActive }"></div>
上传多个字段内容
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
data: {
isActive: true,
hasError: false
}
当然,绑定的数据对象不必内联定义在模板里;利用函数接收
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
- 数组语法
我们可以把一个数组传给 v-bind:class
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
绑定内联样式
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
条件渲染
也就是通过一些指令来说明哪些结构需要显示,哪些不需要显示
如:v-if v-else-if v-show等等上面指令有描述
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if较好。 来自官方文档
列表渲染
v-for
<div id="app">
<li v-for="n in evenNumbers">{{ n }}</li>
<span v-for="n in 10">{{n}}</span>
</div>
var vm = new Vue({
el: "#app",
data: {
numbers: [1, 2, 3, 4, 5]
},
computed: {
evenNumbers: function() {
return this.numbers.filter(function(number) {
return number % 2 === 0
})
}
}
})
- 第二参数(index)用来输出索引值
<ul>
<li v-for="(item ,index) in items" :key="index">{{index}}{{item.message}}</li>
</ul>
- 第三参数(key)
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略 只适用于不依赖子组件状态或临时 DOM 状态为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute
<li v-for="(value,key) in object" :key="key">{{key}}:{{value}}</li>
var vm = new Vue({
el: "#app",
data: {
items: [{
message: "one"
}, {
message: "two"
}],
object: {
title: "lgh",
public: "default",
age: "19"
}
}
})
事件处理
事件处理方法
<div id="example-2">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">Greet</button>
</div>
var example2 = new Vue({
el: '#example-2',
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
}
})
也可以内联处理器中的方法
<button v-on:click="say('hi')">Say hi</button>
methods: {
say: function (message) {
alert(message)
}
事件修饰符
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
按键修饰符(也就是键盘事件)
<div id="app">
<input type="text" v-on:keyup.enter="submit">
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>
</div>
var vm = new Vue({
el: "#app",
data: {},
methods: {
submit: function() {
alert("我嗯了enter键盘了")
},
onClick: function() {
alert("alt+shift")
},
onCtrlClick: function() {
alert("only ctrl")
}
}
})
.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件
表单输入绑定
你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。
它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。
它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
你会发现输入框的内容会自动映射到页面上
下面是一些案例
<div id="app">
<input type="text" v-model="message" placeholder="填写">
<p>message is {{message}}</p>
<textarea name="" id="" cols="30" rows="10" v-model="message1"></textarea>
<hr>
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
<hr>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<hr>
<span>Checked names: {{ checkedNames }}</span>
<hr>
<input type="radio" id="one" value="one" v-model="picked">
<label for="one">one</label>
<input type="radio" id="two" value="two" v-model="picked">
<label for="two">two</label>
<span>你选择的是{{picked}}</span>
<hr>
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
<hr>
<div id="example-6">
<select v-model="selected1" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected1: {{ selected1 }}</span>
</div>
<hr>
<select name="" id="" v-model="selected2">
<option value="" v-for="option in options" v-bind:value="option.value">{{option.text}}</option>
</select>
<span>Selected: {{ selected2 }}</span>
</div>
var vm = new Vue({
el: "#app",
data: {
message: "lgh",
message1: "我是一个好好学习想要成为前端开发程序员的的刘港辉",
checkedNames: [],
checked: "我时",
picked: [],
selected: [],
selected1: [],
selected2: 'A',
options: [{
text: 'One',
value: 'A'
}, {
text: 'Two',
value: 'B'
}, {
text: 'Three',
value: 'C'
}]
},
})
组件基础
组件可以实现复用
- 文件组件
1:创建组件(采用extend扩展)
const school = Vue.extend({
template: ` //组件模板内容
<div>
<h3>学校名称:{{schoolName}}</h3>
<h3>学校地址:{{address}}</h3>
</div>
`, //data必须是一个函数 因此每个实例可以维护一份被返回对象的独立的拷贝
data() {
return {
schoolName: "山西应用科技学院",
address: "太原市小店区北格镇"
}
}
})
2:注册组件
new Vue({
el: "#root",
components: {
// 第一个值是组件标签名 第二个值是实例名称
school: school,
}
})
3:使用组件
<div id="root">
<school></school>
</div>
数据代理
通过一个对象代理对另一个对象的操作
先写一个简单的例子
let obj = {
x: 100
}
let obj1 = {
y: 200
}
Object.defineProperty(obj1, 'x', {
get() {
return obj.x;
},
set(value) {
obj.x = value;
}
})
obj1里面本来没有x这个数值,可以通过defineProperty来把obj里面的x添加到obj1上面;可以实现通过obj1去观察obj里面x的属性 及通过obj1去修改obj里面的属性值
vue中的数据代理
数据代理 通过vm对象来代理data对象中属性的操作;可以更加方便的操作data中的数据
<div id="root">
<h2>{{name}}</h2>
<h2>{{address}}</h2>
</div>
let vm = new Vue({
el: "#root",
data: {
name: '刘港辉',
address: '山西省'
}
})
1:首先我们先创建了一个vm的实例对象 实例对象里面包含 _data 这一属性 (它就等于 data)
2:通过Object.defineProperty()这一API 把 data 对象中的所有属性添加到 vm 上
3:为每一个添加到 vm 的属性都添加一个 geter seter 属性
4:利用 setter 和 getter 去操作 data 的属性
生命周期
- Vue 实例从创建到销毁的过程,就是生命周期。
- 也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,就是 Vue 的生命周期
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
1、beforeCreate(创建前)
表示实例完全被创建出来之前,vue 实例的挂载元素el和数据对象 data 都为 undefined,还未初始化,this指向创建的实例,不能访问到data,computed,watch,methods上的方法和数据,此时,vue组件对象被创建,但是vue对象的属性还没有绑定,即没有值。
2、created(创建后)
数据对象data已存在,可以调用methods中的方法,操作data中的数据,但dom未生成,el未存在
数据对象 data 已存在,可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成,$el 未存在
3、beforeMount(挂载前)
vue 实例的 $el 和 data 都已初始化,挂载之前为虚拟的 dom节点,模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中。data.message 未替换。
4、mounted(挂载后)
vue 实例挂载完成,data.message 成功渲染。内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了。实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,DOM 渲染在 mounted 中就已经完成了。
5、beforeUpdate(更新前)
当 data 变化时,会触发beforeUpdate方法 。data 数据尚未和最新的数据保持同步。
6、updated(更新后)
当 data 变化时,会触发 updated 方法。页面和 data 数据已经保持同步了。
7、beforeDestory(销毁前)
组件销毁之前调用 ,在这一步,实例仍然完全可用。
8、destoryed(销毁后)
组件销毁之后调用,对 data 的改变不会再触发周期函数,vue 实例已解除事件监听和 dom绑定,但 dom 结构依然存在。
更多生命周期信息查看这里