1.初识Vue
Vue是一套用于构建用户界面的渐进式框架,Vue 被设计为可以自底向上逐层应用,Vue的核心是只关注视图层(如何理解),不仅易于上手,还便于与第三方库或既有项目整合。
- 渐进式框架:渐进也可以理解为一步一步的意思,大概意思就是使用Vue的时候,并不需要把整个框架的所有东西都用上,可以根据实际情况选择你需要的部分;也意味着可以使用Vue作为项目的一部分。
- 自底向上逐层应用:由基层开始做起,把基础的东西写好,再逐层往上添加效果和功能。
- 组件化:按功能分为不同组件,利于代码复用。
- 声明式:编程范式的一种,简单的说,你只需要告诉计算机,你要得到什么样的结果,计算机则会完成你想要的结果。以Vue为例,在页面中通过 { {xxx}} 显示一个data里面的变量,你只需要改变这个变量,页面就会跟着刷新,这就是你只需要结果,vue 内部去处理过程,这就是声明式编程。对应命令式编程(原生js就是命令式,你得详细地命令如何处理)。
1.1 MVVM是什么?
MVVM 模式,顾名思义即 Model-View-ViewModel 模式。
1.1.1 MVVM简介
Model 层:
对应数据层的域模型,它主要做域模型的同步。
通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同 步。在层间关系⾥,它主要⽤于抽象出 ViewModel 中视图的data。
View 层:
作为视图模板存在,在 MVVM ⾥,整个 View 是⼀个动态模板,在前端开发中,通常就是指DOM。
除了定义结构、布局外,它展示的是 ViewModel 层的数据和状态。View 层不负责处理状态, View 层做的是数据绑定的声明、 指令的声明、 事件绑定的声明。
ViewModel 层:
把 View 需要的层数据暴露,并对 View 层的 数据绑定声明、 指令声明、 事件绑定声明 负责,也就是处理 View 层的具体业务逻辑。 ViewModel 底层会做好绑定属性的监听。
当 ViewModel 中数据变化, View 层会得到更新;⽽当 View 中声明了数据的双向绑定(通常是表单元素),框架也会监听 View 层(表单)值的变化。⼀旦值变化,View 层绑定的 ViewModel 中的数据也会得到⾃动更新。
1.1.2 计数器案例
<!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 src="./js/vue.js"></script>
</head>
<body>
<!-- dom是 view层 -->
<div id="app">
<div>当前计数:{
{num}}</div>
<!-- 命令式,不需要获取元素再添加监听事件了 -->
<button @click="num++">+</button>
<button @click="num--">-</button>
</div>
<script>
// vm实例是 viewModel层
// viewModerl层通过数据绑定让model实时的在DOM中显示
// viewModerl层通过事件监听来监听DOM事件,并改变vm中的data
let vm = new Vue({
el: '#app',
// data是 model层
data() {
return {
num: 0,
};
},
});
</script>
</body>
</html>
1.2 Vue的特点
- 遵循 MVVM 模式,解耦视图和数据
- 编码简洁,体积小,运行效率高,适合移动/PC端开发
- 它本身只关注 UI,可以轻松引入 vue 插件或其它第三方库开发项目
- 采用组件化模式,提高代码复用率、且让代码更好维护
- 声明式编码,让编码人员无需直接操作DOM,提高开发效率
- 状态管理
- 使用虚拟DOM和Diff算法,尽量复用DOM节点
1.3 Vue与其他前端 JS 框架的关联
- 借鉴 angular 的 模板 和 数据绑定 技术
- 借鉴 react 的 组件化 和 虚拟DOM 技术
1.4 Vue 扩展插件
- vue-cli:vue 脚手架
- vue-resource(axios):发送ajax请求
- vue-router:路由
- vuex:状态管理(它是 vue 的插件但是没有用 vue-xxx 的命名规则)
- vue-lazyload:图片懒加载
- vue-scroller:页面滑动相关
- mint-ui:基于 vue 的 UI 组件库(移动端)
- element-ui:基于 vue 的 UI 组件库(PC 端)
2. 创建Vue应用
2.1 Vue的两个版本(开发者/生产环境)
- 开发版本:包含完整的警告和调试模式
- 生产版本:删除了警告,37.36KB min+gzip
关闭生产提示
// 设置为 false 以阻止 vue 在启动时生成生产提示。
Vue.config.productionTip = false;
2.2 安装Vue Devtools
- vue-devtools是一款基于chrome游览器的插件,用于调试vue应用,这可以极大地提高我们的调试效率。
2.3 引入(安装)Vue的两种方式
- 本地引入
- 本地下载vue.js文件,并引入
<script type="text/javascript" src="../js/vue.js"></script>
- CDN引入
- CDN:内容分发网络,是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。
- 不需要下载vue.js文件 ,引入也可以选择版本哦
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
- npm安装vue-cli构建
- 脚手架直接构建,后续补充操作。
2.4 创建Vue实例对象的步骤
- 准备一个容器 (模板)
- Vue.config.productionTip = false 可以关闭生产提示
- new Vue({})创建Vue实例传入,选项对象options
- 配置options,如:el、data、methods、computed、watch、生命周期钩子…
- 当一个 Vue 实例(vm)被创建时,它将
data
对象中的所有的 property 加入到Vue实例对象的响应式系统中,之后在模板里可以直接使用data里的属性。
例:
<!-- 容器(模板) -->
<!-- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法(插值/指令语法) -->
<div id="app">
{
{message}}
</div>
// 声明一个Vue实例对象,Vue构造函数的参数就是配置项;真实开发中只有一个Vue实例,并且会配合着组件一起使用
var vm = new Vue({
// el值通常为css的选择器,会去寻找容器,就把【当前】Vue实例和容器建立了联系
// data中用于存储数据,数据供el指定的容器去使用;值我们暂时先写成一个对象,实际开发中为函数的形式
// 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
el:'#app',
data:{
message:"hello vue!"
}
})
注意点:
1. 此时,data和DOM就被建立了关联(模型和视图解耦),所有数据都是响应式的(单向数据绑定,通过Object.defineProperty的getter、setter进行数据劫持实现的;而data中的数据出现在vm身上是数据代理)。
2. 打开浏览器控制台,修改app.message的值,页面内容也会改变。
3. 值得注意的是只有当实例被创建时就已经存在于 data
中的 property 才是响应式的。
4. 通过…设置,可使得后添加的也是响应式。
5. 使对象不可被修改的方法:Object.freeze()
var obj = {
foo: 'bar'}
Object.freeze(obj)
new Vue(
{
el: '#app',
data: obj
}
)
<div id="app">
<p>{
{ foo }}</p>
<!-- 这里的 `foo` 不会更新! -->
<button v-on:click="foo = 'baz'">Change it</button>
</div>
2.3.1关于el的两种写法的区别
el(element)的值通常是选择器,用于挂载要管理的元素 使得Vue实例(viewModel)和容器(DOM)关联一一el有两种写法
(1) new Vue时候配置el属性。
const vm = new Vue({
el:'#root', //第一种写法
data:{
name:'pqq'
}
})
(2) 先创建Vue实例,随后再通过vm.$mount(’#root’)指定el的值。
data:{
name:'pqq'
}
})
vm.$mount('#root') //第二种写法,挂载
2.3.2关于data的两种写法的区别
(1) 对象式
data: {
a:1
}
(2)函数式(组件中必须使用这种写法!!!)
data() {
return {
a:1
}
}
注意点!why:
JS中,简单的数据类型就是浅拷贝,复杂的数据类型就需要用到深拷贝。
因为项目中每个组件都可能会被复用,组件作为标签每次被复用,都是一个相应的组件实例被new,只有使用函数式而非对象式,每个组件实例之间的数据才不会相互影响;类似深拷贝!
2.3.3 两种书写options的方式
Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 $
,以便与用户定义的 property 区分开来。例如:
var data = {
a: 1 }
var vm = new Vue({
el: '#example', data: data})
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用})
2.3.3一个重要的原则
由Vue管理的函数,如data() {}、mounted(){} …的this指向Vue实例对象或者组件实例对象,因此一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
因为箭头函数中的this指向的是定义时的this,而不是执行时的this。
3. Vue的生命周期
3.1 Vue的生命周期是什么
生命周期
…
- 又名:生命周期回调函数、生命周期函数、生命周期钩子。
- 是什么:new Vue({})其实是调用了Vue源码里的Vue构造函数,而生命周期钩子就是在执行到某一时刻,帮我们自动调用的options写的,有着特殊名称的回调函数。
- 作用:通知我们实例化到哪一步了,于是我们可以在某些时期在函数内部做想做的事情。
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
- 生命周期函数中的this指向是 Vue实例对象 或 组件实例对象。
注意点:不要在选项 property 或回调上使用箭头函数!
3.2 生命周期钩子
绿色是Vue源码中的函数,红色是hook即生命周期钩子。
疑问待解决:
- 为什么在模板里可以直接使用data的属性
- 为什么this.xxx可以获取data的属性。。。
- 2.3.3组件data只能使用函数涉及组件化,待完善