写在开头
Vue的官网教程非常详细,深入学习优先推荐官网文档
本文通过学习培训机构教程总结而来,可能某些地方有纰漏或不足,希望和大家一起学习探讨。
目录
一、Vue简介
1.1 什么是Vue
是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。
1.2 Vue的特性
vue框架的特性,主要体现在如下两个方面:
- 数据驱动视图
- 双向数据绑定
1.2.1 数据驱动视图
数据的变化会驱动视图自动更新、程序员只需将数据维护好,页面结构会被Vue自动渲染出来
- 好处:当页面数据发生变化时,页面会自动重新渲染!
- 注意:数据驱动视图是单向的数据绑定。
1.2.2 双向数据绑定
在填写表单时,双向数据绑定可以辅助开发者在不操作DOM 的前提下,自动把用户填写的内容同步到数据源中。示意图如下:
- 好处:开发者不再需要手动操作 DOM 元素,来获取表单元素最新的值!
1.2.3 MVVM
MVVM 是 Vue 实现数据驱动视图和双向数据绑定的核心原理。
MVVM 指的是 Model、 View 和 ViewModel, 它把每个 HTML 页面都拆分成了这三个部分,如图所示:
- Model数据源,View视图,ViewModel就是Vue的实例
1.2.4 MVVM的工作原理
ViewModel 作为MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起。
- 当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构
- 当表单元素的值发生变化时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到 Model 数据源中
二、Vue的基本使用
2.1 基本使用步骤
- 导入 vue.js 的script 脚本文件
- 在页面中声明一个将要被 vue 所控制的 DOM 区域
- 创建 vm 实例对象(vue 实例对象)
<body>
<!-- 希望 Vue 能够控制下面的这个 div,帮我们在把数据填充到 div 内部 -->
<div id="app">{{ username }}</div>
<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./vue.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
// 创建 Vue 的实例对象
const vm = new Vue({
// el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
el: '#app',
// data 对象就是要渲染到页面上的数据
data: {
username: 'zhangsan'
}
})
</script>
</body>
2.2 基本代码与 MVVM 的对应关系
三、Vue的调试工具--vue-devtools
vue 官方提供的 vue-devtools 调试工具,能够方便开发者对 vue 项目进行调试与开发。
下载.crx结尾的安装包,谷歌浏览器=>更多工具=>扩展程序=>开发者模式=>安装插件
由于编译较为麻烦,此处提供编译好的安装包,方便安装,若自己尝试请查询相关教程
链接: https://pan.baidu.com/s/1ZIdtCq0TMwQ0_0v5jIxgug?pwd=my8d 提取码: my8d
四、Vue的指令
4.1 指令类型
指令(Directives)是Vue为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。
Vue中的指令按照不同的用途可以分为如下6大类:
- 内容渲染指令
- 属性绑定指令
- 事件绑定指令
- 双向绑定指令
- 条件渲染指令
- 列表渲染指令
4.2 内容渲染指令
内容渲染指令用来辅助开发者渲染DOM元素的文本内容,常用的内容渲染指令有以下3个:
- v-text
- {{ }}
- v-html
代码以及演示效果如下 :
<div id="app">
<p v-text="username"></p>
<p v-text="gender">性别:</p>
<hr>
<p>姓名:{{ username }}</p>
<p>性别:{{ gender }}</p>
<hr>
<div v-text="info"></div>
<div>{{ info }}</div>
<div v-html="info"></div>
</div>
data: {
username: 'zhangsan',
gender: '女',
info: '<h4 style="color: red; font-weight: bold;">欢迎大家来学习 vue.js</h4>'
}
由此可见:
- v-text 会覆盖元素内部原有的内容
- {{}} 为内容的占位符,不会覆盖原有的内容,较为常用,只能写简单的js表达式
- v-html 可以渲染包含html标签的字符串
4.3 属性绑定指令
v-bind:属性名 或 :属性名
插值表达式只能用在元素的内容节点,不能用在属性节点
如果需要为元素的属性动态绑定属性值,则需要用到 v-bind 属性绑定指令。用法示例:
<div id="app">
<input type="text" :placeholder="tips"> // placeholder无内容显示,开始输入内容消失
<hr>
<!-- vue 规定 v-bind: 指令可以简写为 : -->
<img :src="photo" alt="" style="width: 150px;">
</div>
<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
// 创建 Vue 的实例对象
const vm = new Vue({
// el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
el: '#app',
// data 对象就是要渲染到页面上的数据
data: {
tips: '请输入用户名',
photo: 'https://cn.vuejs.org/images/logo.svg',
}
})
</script>
在 vue 提供的模板渲染语法中,除了支持绑定简单的数据值之外,还支持Javascript 表达式的运算,例如:
- 如上图最后一个例子,在使用v-bind属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号。
- 如果没有单引号,不会被认为是字符串而会被认为是变量,数据源中无此变量则会报错。
4.4 事件绑定指令
Vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听。语法格式如下:
注意:原生 DOM 对象有 onclick、 oninput、 onkeyup 等原生事件。
替换为 vue 的事件绑定形式后分别为:v-on:click、v-on:input、 v-on:keyup
<div id="app">
<p>count 的值是:{{ count }}</p>
<!-- 在绑定事件处理函数的时候,可以使用 () 传递参数 -->
<!-- v-on: 指令可以被简写为 @ -->
<button v-on:click="add(1)">+1</button>
<button v-on:click="sub">-1</button>
</div>
<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
// 创建 Vue 的实例对象
const vm = new Vue({
// el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
el: '#app',
// data 对象就是要渲染到页面上的数据
data: {
count: 0
},
// methods 的作用,就是定义事件的处理函数
methods: {
add(n) {
// 在 methods 处理函数中,this 就是 new 出来的 vm 实例对象
// console.log(vm === this)
//console.log(vm)
// vm.count += 1
this.count += n
},
sub() {
// console.log('触发了 sub 处理函数')
this.count -= 1
}
}
})
</script>
- 给谁绑定事件就给谁加v-on,后面跟事件(如click)和处理函数(如add)。
- 如果传参就在定义处理函数小括号里加形参,绑定事件小括号里加实参。
- 通过this. 调用数据源中的变量与方法
- v-on:简写为@ 例如v-on:click改写为@click
- 如果不传实参,则默认传一个事件对象给处理函数
- vue 提供了内置变量,名字叫做 $event,它就是原生 DOM 的事件对象 e,可以用于传实参。
<button @click="add($event, 1)">+N</button>
- target属性: target:button。
- 由此就可以获得点击对象
4.4.1 事件修饰符
- 原生 js 中常用事件对象的 preventDefault() 来阻止默认行为,stopPropagation() 来阻止事件冒泡
- 在事件处理函数中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。
- 因此, vue 提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发进行控制。
常用的5 个事件修饰符如下:
4.4.2 按键修饰符
在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符,例如:
4.5 双向绑定指令
vue 提供了 v-model 双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据。
在提交表单或采集数据时,不需要再操作DOM,只要修改了表单文本框,就会修改数据源,直接用this. 就能获得最新的数据源。
v-bind: value="username" 与 v-model="username"的区别:
前者是单向绑定,数据源改变驱动页面数据改变,但页面上的改动不会同步到数据源;
后者是双向绑定。
只有表单元素使用v-model才有意义。如
- input: type="radio"; type="checkbox"; type="xxx"
- textarea
- select
vue内部会判断v-model绑定的元素类型,有选择地控制元素的属性
(例如input type="checkbox"绑定check属性,input type="text"绑定value属性)
4.5.1 v-model指令的修饰符
为了方便对用户输入的内容进行处理,vue 为 V-model 指令提供了3 个修饰符,分别是:
应用场景:
.number
用户输入表单的是字符串,不能进行数值的计算(只能字符串拼接),可以用.number转换成数值类型再计算。
.trim
如输入用户名的场景时我们希望去掉用户可能因为误操作在首尾输入的空格,可以使用.trim,它不会处理输入内容中间的空格。
.lazy
因为使用v-model时表单输入框和数据源中的数据是实时更新的,在改变输入框内的内容过程中没有必要更新数据源中的数据,会引起性能上的问题,所以可以使用.lazy,在表单输入内容修改完成("change"时,如失去焦点)再同步数据源的数据。
<body>
<!-- 希望 Vue 能够控制下面的这个 div,帮我们把数据填充到 div 内部 -->
<div id="app">
<input type="text" v-model.number="n1"> + <input type="text" v-model.number="n2"> = <span>{{ n1 + n2 }}</span>
<hr>
<input type="text" v-model.trim="username">
<button @click="showName">获取用户名</button>
<hr>
<input type="text" v-model.lazy="username">
</div>
<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
// 创建 Vue 的实例对象
const vm = new Vue({
// el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
el: '#app',
// data 对象就是要渲染到页面上的数据
data: {
username: 'zhangsan',
n1: 1,
n2: 2
},
methods: {
showName() {
console.log(`用户名是:"${this.username}"`)
}
},
})
</script>
</body>
4.6 条件渲染指令
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:
- v-if
- v-show
区别:
v-if 是通过动态添加或移除元素标签达到显示或隐藏的功能
v-show是给元素标签添加或删除 style="display: none" 样式属性达到
可以看出频繁切换元素显示状态,v-show对性能优化更好
若进入页面时某元素默认不需要被展示,而且以后也很可能不需要被展示,v-if对性能更好
实际开发中v-if用的更多,因为性能影响不是很大
v-else(需要与v-if 配套,用法如同if else语句)
v-else-if(需要与v-if配套,用法如同 if else if 语句)
<body>
<!-- 希望 Vue 能够控制下面的这个 div,帮我们把数据填充到 div 内部 -->
<div id="app">
<p v-if="flag">这是被 v-if 控制的元素</p>
<p v-show="flag">这是被 v-show 控制的元素</p>
<hr>
<div v-if="type === 'A'">优秀</div>
<div v-else-if="type === 'B'">良好</div>
<div v-else-if="type === 'C'">一般</div>
<div v-else>差</div>
</div>
<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
// 创建 Vue 的实例对象
const vm = new Vue({
// el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
el: '#app',
// data 对象就是要渲染到页面上的数据
data: {
// 如果 flag 为 true,则显示被控制的元素;如果为 false 则隐藏被控制的元素
flag: false,
type: 'A'
}
})
</script>
</body>
4.7 列表渲染指令
vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。
v-for 指令需要使用 item in items 形式的特殊语法,其中:
- items 是待循环的数组
- item 是被循环的每一项
v-for中的索引
v-for 指令还支持一个可选的第二个参数,即当前项的索引。语法格式为 ( item, index ) in items,示例代码如下:
注意:v-for指令中的 item 项和 index 索引都是形参,可以根据需要进行重命名。例如 ( user , i ) in userlist
需要索引再加()
使用v-for的元素本身也可以访问数组的item
<tr v-for="(item, index) in list" :key="item.id">
<td>{{ index }}</td>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
官方建议:只要用到了 v-for 指令,那么一定要绑定一个 :key 属性,而且,尽量把 id 作为 key 的值,官方对 key 的值类型,是有要求的:字符串或数字类型,key 的值是千万不能重复的,否则会终端报错:Duplicate keys detected
key值的注意事项:
- key 的值只能是字符串或数字类型
- key 的值必须具有唯一性(即:key 的值不能重复)
- 建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)
- 使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)
- 建议使用 v-for 指令时一定要指定 key 的值(既提升性能、又防止列表状态紊乱)
<tr v-for="(item, index) in list" :key="item.id">
<td>{{ index }}</td>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
小案例:品牌列表
案例效果图:
<!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>品牌列表案例</title>
<link rel="stylesheet" href="./lib/bootstrap.css">
<link rel="stylesheet" href="./css/brandlist.css">
</head>
<body>
<div id="app">
<!-- 卡片区域 -->
<div class="card">
<div class="card-header">
添加品牌
</div>
<div class="card-body">
<!-- 添加品牌的表单区域 -->
<!-- form 表单元素有 submit 事件 -->
<form @submit.prevent="add">
<div class="form-row align-items-center">
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">品牌名称</div>
</div>
<input type="text" class="form-control" placeholder="请输入品牌名称" v-model.trim="brand">
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-2">添加</button>
</div>
</div>
</form>
</div>
</div>
<!-- 表格区域 -->
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">品牌名称</th>
<th scope="col">状态</th>
<th scope="col">创建时间</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>
<div class="custom-control custom-switch">
<!-- 使用 v-model 实现双向数据绑定 -->
<input type="checkbox" class="custom-control-input" :id="'cb' + item.id" v-model="item.status">
<!-- 使用 v-if 结合 v-else 实现按需渲染 -->
<label class="custom-control-label" :for="'cb' + item.id" v-if="item.status">已启用</label>
<label class="custom-control-label" :for="'cb' + item.id" v-else>已禁用</label>
</div>
</td>
<td>{{ item.time }}</td>
<td>
<a href="javascript:;" @click="remove(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script src="./lib/vue-2.6.12.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户输入的品牌名称
brand: '',
// nextId 是下一个,可用的 id
nextId: 4,
// 品牌的列表数据
list: [
{ id: 1, name: '宝马', status: true, time: new Date() },
{ id: 2, name: '奔驰', status: false, time: new Date() },
{ id: 3, name: '奥迪', status: true, time: new Date() },
],
},
methods: {
// 点击链接,删除对应的品牌信息
remove(id) {
this.list = this.list.filter(item => item.id !== id)
},
// 阻止表单的默认提交行为之后,触发 add 方法
add() {
// 如果判断到 brand 的值为空字符串,则 return 出去
if (this.brand === '') return alert('必须填写品牌名称!')
// 如果没有被 return 出去,应该执行添加的逻辑
// 1. 先把要添加的品牌对象,整理出来
const obj = {
id: this.nextId,
name: this.brand,
status: true,
time: new Date()
}
// 2. 往 this.list 数组中 push 步骤 1 中得到的对象
this.list.push(obj)
// 3. 清空 this.brand;让 this.nextId 自增 +1
this.brand = ''
this.nextId++
}
},
})
</script>
</body>
</html>
五、Vue过滤器
由于Vue 3中将此部分删除,所以只需要明白工作流程以及原理即可
5.1 定义过滤器
过滤器 (Filters)是 vue 为开发者提供的功能,常用于文本的格式化。
过滤器可以用在两个地方:插值表达式和 v-bind 属性绑定。
过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”进行调用,示例代码如下:
- capitalize是自定义的首字母大写的函数
- message作为参数传给这个函数
- 花括号得到的是函数的返回值
过滤器函数必须被定义到filters节点下(与methods平级)
过滤器一定要有return返回值
过滤器的形参中,val代表管道符前面的那个值(不一定要叫val,形参名合法就行,只是可以通过形参获取管道符前面那个待处理的值)
示例代码:
<div id="app">
<p>message 的值是:{{ message | capitalize }}</p>
</div>
<script src="./lib/vue-2.6.12.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
message: 'hello vue.js'
},
// 过滤器函数,必须被定义到 filters 节点之下
// 过滤器本质上是函数
filters: {
// 注意:过滤器函数形参中的 val,永远都是“管道符”前面的那个值
capitalize(val) {
// 字符串有 charAt 方法,这个方法接收索引值,表示从字符串中把索引对应的字符,获取出来
// val.charAt(0)
const first = val.charAt(0).toUpperCase()
// 字符串的 slice 方法,可以截取字符串,从指定索引往后截取
const other = val.slice(1)
// 强调:过滤器中,一定要有一个返回值
return first + other
}
}
})
</script>
5.2 私有过滤器和全局过滤器
在flters 节点下定义的过滤器,称为”私有过滤器〞,因为它只能在当前 vm 实例所控制的el区域内使用。
如果希望在多个 vue 实例之间共享过滤器,则可以按照如下的格式定义全局过滤器:
实际开发中更多的是定义全局过滤器
全局过滤器要放在VUE实例对象前面
如果全局过滤器和私有过滤器名字一致,会根据就近原则调用私有过滤器
小案例:品牌列表-时间格式优化:
引入day.js(官网跳转)
详细使用方法查询官网文档,此处演示使用后的代码
<td>{{ item.time | dateFormat }}</td>
...
<!-- 只要导入了 dayjs 的库文件,在 window 全局,就可以使用 dayjs() 方法了 -->
<script src="./lib/dayjs.min.js"></script>
...
<script>
// 声明格式化时间的全局过滤器
Vue.filter('dateFormat', function (time) {
// 1. 对 time 进行格式化处理,得到 YYYY-MM-DD HH:mm:ss
// 2. 把 格式化的结果,return 出去
// 直接调用 dayjs() 得到的是当前时间
// dayjs(给定的日期时间) 得到指定的日期
const dtStr = dayjs(time).format('YYYY-MM-DD HH:mm:ss')
return dtStr
})
...
</script>
5.3 连续调用多个过滤器
过滤器可以串联地进行调用,例如:
5.4 过滤器传参
过滤器的本质是 JavaScript 函数,因此可以接收参数,格式如下:
5.5 过滤器的兼容性
过滤器仅在 Vue 2.X 和1.X中受支持,在vue 3.X 的版本中剔除了过滤器相关的功能
在企业级项目开发中:
- 如果使用的是 2.X版本的Vue,则依然可以使用过滤器相关的功能
- 如果项目已经升级到了 3.X版本的 Vue,官方建议使用计算属性或方法代替被剔除的过滤器功能
六、watch侦听器
6.1 什么是watch侦听器
watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。
语法格式如下:
所有的侦听器都必须定义到watch节点下。
侦听器本质是个函数,要监听哪个数据,就把它作为方法名,只要它发生了变化就会触发这个函数
注意传参时,新值在前,旧值在后。
6.2 应用场景:使用watch检测用户名是否可用
实例:获取用户输入的用户名,使用axios发Ajax去调接口请求服务器,看该用户名是否被占用。
watch: {
// 监听 username 值的变化
async username(newVal) {
if (newVal === '') return
// 使用 axios 发起请求,判断用户名是否可用
const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal)
console.log(res)
}
}
补充:下例是使用jquery中的Ajax发请求,判断 newVal 是否被占用。
watch: {
// 侦听器本质上是一个函数,要监视哪个数据的变化,就把数据名作为方法名即
// 新值在前,旧值在后
username(newVal) {
//传空值会报错,所以判断为空时返回,不会发请求
if (newVal === '') return
// 1. 调用 jQuery 中的 Ajax 发起请求,判断 newVal 是否被占用!!!
$.get('https://www.escook.cn/api/finduser/' + newVal, function (result) {
console.log(result)
})
}
}
新需求:用户一进该页面就传输入框中原有的值,发送请求。
侦听器的格式:
1、方法格式的侦听器
缺点1:无法在刚进入页面的时候自动触发;
缺点2:如果侦听的是一个对象,对象中的属性发生了变化,不会触发侦听器。
2、对象格式的侦听器
好处1:可以通过immediate选项让侦听器自动触发;
好处2:可以通过deep选项,让侦听器深度侦听对象中每个属性的变化。
为了方便书写一般建议定义成方法格式,要使用immediate时再使用对象格式。
6.3 immediate 选项
watch: {
username: {
// handler 是固定写法,表示当 username 的值变化时,自动调用 handler 处理函数
handler: async function (newVal) {
if (newVal === '') return
const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal)
console.log(res)
},
// 表示页面初次渲染好之后,就立即触发当前的 watch 侦听器
immediate: true
}
}
immediate: true表示一进页面即触发该侦听器。
6.4 deep选项
如果 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep选项,代码示例如下:
如果只想监听对象中单个属性的变化,则可以按照如下的方式定义 watch 侦听器:
示例代码(deep选项和一步到位两种写法):
<div id="app">
<input type="text" v-model="info.username">
<input type="text" v-model="info.address.city">
</div>
<script src="./lib/vue-2.6.12.js"></script>
<script src="./lib/jquery-v3.6.0.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
// 用户的信息对象
info: {
username: 'admin',
address: {
city: '北京'
}
}
},
// 所有的侦听器,都应该被定义到 watch 节点下
watch: {
/* info: {
handler(newVal) {
console.log(newVal)
},
// 开启深度监听,只要对象中任何一个属性变化了,都会触发“对象的侦听器”
deep: true
} */
// 如果要侦听的是对象的子属性的变化,则必须包裹一层单引号
'info.username'(newVal) {
console.log(newVal)
}
}
})
</script>
二、计算属性
1. 什么是计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
在这个地方,模板不再是简单的声明式逻辑。
你必须看一段时间才能意识到,这里是想要显示变量 message
的翻转字符串。当你想要在模板中的多处包含此翻转字符串时,就会更加难以处理。
所以,对于任何复杂逻辑,你都应当使用计算属性。
<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('')
}
}
})
所有的计算属性,都要定义到 computed 节点之下。
计算属性的特点
- 虽然计算属性在声明的时候被定义为方法,但是计算属性的本质是一个属性
- 计算属性会缓存计算的结果,只有计算属性依赖的数据变化时,才会重新进行运算
三、vue-cli
1. 什么是单页面应用程序
单页面应用程序(英文名:Single Page Application) 简称 SPA, 顾名思义,指的是一个 Web 网站中只有唯一的一个 HTML 页面,所有的功能与交互都在这唯一的一个页面内完成。
例如资料中的这个 Demo 项目:
2. 什么是 vue-cli
vue-cli是 Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化的 Vue 项目的过程。
引用自 vue-cli 官网上的一句话:
程序员可以专注在撰写应用上,而不必花好几天去纠结 webpack 配置的问题。
中文官网: Vue CLI
3. 安装和使用
vue-cli 是 npm 上的一个全局包,使用 npm install 命令,即可方便的把它安装到自己的电脑上:
npm install -g @vue/cli
终端输入“vue -V回车”,可以显示版本号的话说明安装成功。
基于 vue-cli 快速生成工程化的 Vue 项目:
vue create 项目的名称
使用方向键移动,回车进行选择,第一次使用时没有demo那个选项,1为Vue 3 版本,2为Vue 2 版本,3为自定义选择功能
为了方便了解学习,此处选择 3 ‘Manually select features’选项。
空格键选中功能(打上*号)或取消选中,这里选中第一项安装Babel(解决兼容性)、CSS-Pre-processors安装CSS预处理器。
默认选中了Linter/Formater代码规范,取消该选项(因为太严格了,多一个空格都会报错,后面再讲述如何使用)回车进入下层
选择使用的Vue版本(选择2.0)和CSS预处理器(选择Less)
选择第三方插件的配置文件是独立存放还是放package.json里
创建完成后,根据蓝色命令操作完成。
serve是开发阶段要运行的命令(npm run serve);build是项目开发完要上线时要运行的命令(npm run build) 。
![]()
项目结构图 node_modules:所有的第三方包;
public: 公共资源文件夹下的favicon是网站的小图标;
index.html是单页面程序的首页
src: 下是项目的源代码;
babel.config.js:babel配置文件;
package.json: 包管理配置文件;
![]()
src目录下文件 assets 文件夹:存放项目中用到的静态资源文件,例如 css样式表、图片资源;
components文件夹:程序员封装的、可复用的文件;
main.js:是项目的入口文件,整个项目的执行,要执行main.js(webpack配置文件中的entry);
App.vue:是项目的根组件。
4. vue 项目的运行流程
在工程化的项目中(此处是vue-cli创建出来的),vue 要做的事情很单纯:通过 main.js 把 App.vue 渲染到 index.html 的指定区域中。
其中:
- App.vue 用来编写待渲染的模板结构
- index.html 中需要预留一个 el 区域
- main.js 把 App.vue 渲染到了 index.html 所预留的区域中
怎么渲染的呢:
// 导入 vue 这个包,得到 Vue 构造函数
import Vue from 'vue'
// 导入 App.vue 根组件,将来要把 App.vue 中的模板结构,渲染到 HTML 页面中
import App from './App.vue'
Vue.config.productionTip = false
// 创建 Vue 的实例对象
new Vue({
// 把 render 函数指定的组件,渲染到 HTML 页面中
render: h => h(App)
}).$mount('#app')
// Vue 实例的 $mount() 方法,作用和 el 属性完全一样!
render函数的作用:让指定的结构替换掉Vue控制区域el所在的结构。
即,index.html中的<div id="app"></div>相当于一个占位符,会被App.vue中的模板语法替换
.$mount函数的作用和指定el一样
render函数中渲染的是哪个.vue组件,那么这个组件就叫做“根组件”。
5. 组件的基本使用
在Component文件夹下新建组件Test.vue
<template>
<div>
<h3>
这是用户自定义的Test.vue
</h3>
</div>
</template>
在main.js中导入该组件,并使用该组件
import Test from './Test.vue'
...
new Vue({
//el:'#app',
render: h=>h(Test)
}).$mount('#app')
这时Test.vue中的模板结构会替代index.html中id为app的div
再写个应用.$mount的案例:
<div id="app">{{username}}</div>
<script src="./lib/vue-2.6.12.js"></script>
<script>
const vm = new Vue({
data: {
username: 'admin'
}
})
vm.$mount('#app')
</script>