Vue 介绍
什么是 vue ?
- 构建用户界面
- 用 vue 往 html 页面中填充数据,非常的方便
- 框架
- 框架是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能!
- 要学习 vue,就是在学习 vue 框架中规定的用法!
- vue 的指令、组件(是对 UI 结构的复用)、路由、Vuex、vue 组件库
- 只有把上面老师罗列的内容掌握以后,才有开发 vue 项目的能力!
vue 的两个特性
-
数据驱动视图:
- 数据的变化会驱动视图自动更新
- 好处:程序员只管把数据维护好,那么页面结构会被 vue 自动渲染出来!
-
双向数据绑定:
在网页中,form 表单负责采集数据,Ajax 负责提交数据。
- js 数据的变化,会被自动渲染到页面上
- 页面上表单采集的数据发生变化的时候,会被 vue 自动获取到,并更新到 js 数据中
注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)
MVVM
MVVM 是 vue 实现数据驱动视图和双向数据绑定的核心原理。
MVVM 的工作原理
ViewModel
作为 MVVM 的核心,是它把当前页面的数据源
(Model)和页面的结构
(View)连接在了一起。
当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构。
当单元素的值发生变化表时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到 Model 数据源中
起步
第一个Vue程序:
-
导入开发版本的 Vue.js
-
创建 Vue实例对象,设置
el
属性和data
属性 -
使用简洁的模板语法
把数据渲染到页面
上{ {message}}
基本代码与 MVVM 的对应关系
插件库
day.js 快速日期格式化
解决格式化Vue文件时 逗号、分号问题 :
在根目录中,添加一个 .prettierrc.json
配置文件,写入:
{
"singleQuote": true,
"semi": false,
"trailingComma": "none"
}
一劳永逸方法:
-
在电脑上的用户目录下新建一个
.prettierrc.json
文件,同理上面的参数。 -
在 **Vs code **的
setting.json
中添加配置路径:// 设置 配置文件,解决格式化vue文件时逗号、分号爆红问题 // 这里注意配置路径,记得使自己计算机上的用户名 "prettier.configPath": "C:/Users/mi/.prettierrc.json",
解决格式化时函数括号前的空格问题 :
- Prettier 格式化插件无法处理函数括号前添加空格问题
解决办法一、在当前项目里的 .eslintrc.js
里 rules 规则里添加忽略加空格爆红提示 :
'space-before-function-paren':['error','never']
解决办法二: 使用 Prettier now
插件可以解决此问题。
vue 指令
1. 内容渲染指令
v-text
设置标签的内容, 默认写法会 覆盖元素内部原有的内容 , 内部支持写表达式。{ { }}
插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!v-html
指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!
注意:插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!
2. v-bind 属性绑定属性
- 在 vue 中,可以使用
v-bind:
指令,为元素的属性动态绑定值; - 简写是英文的
:
-
在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:
<div :title="'box' + index">这是一个 div</div>
-
使用 v-bind 在元素绑定时希望内传入 Number数值时,避免被解析成字符串
<select v-model='value'> <option :value='数字'>...</option> </select>
3. v-on 事件绑定属性
-
v-on:
简写是@
-
语法格式为:
<p> count的值是:{ { count }}</p> <button @click="add"></button> methods: { add() { // 如果在方法中要修改 data 中的数据,可以通过 this 访问到 this.count += 1 } }
$event
在事件绑定时,会有一个原生DOM 的事件对象 e,如果事件对象传入参数,默认的事件对象会被覆盖。
$event
的应用场景:如果默认的事件对象 e 被覆盖了,则可以手动传递一个 $event。
例如:
// 点击按钮让count值 递增,绑定点击事件并传参
<button @click="add(3, $event)"></button>
methods: {
add(n, e) {
// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
this.count += 1
}
}
事件修饰符:
事件绑定期间非常好玩的一个东西,对事件的触发进行控制。
-
.prevent
<a @click.prevent="xxx">链接</a>
-
.stop
<button @click.stop="xxx">按钮</button>
事件修饰符
说明
.prevent
阻止默认行为
(如:阻止a链接的跳转,阻止表单提交等)
.stop
阻止冒泡事件
.capture
以捕获模式触发当前的事件处理函数
.once
绑定的事件只触发一次
.self
只有在event.target 是当前元素自身时触发事件处理函数
按键修饰符
按键
键码值
使用
Enter
13
.enter
Tab
9
.tab
Delete
46
.delete (捕获“删除”和“退格”按键)
Esc
27
.esc
BackSpace
8
.space
Up Arrow
38
.up
Left Arrow
37
.left
Right Arrow
39
.right
Dw Arrow
40
.down
1.自定义其他的按键别名:
Vue.config.keyCodes.f6 = 118
<input @keyup.f6="xxx" /> // 只有单击f6键才会触发xxx的回调
2.多个按键一并触发该事件
@keyup.ctrl.enter="XXX" // 按下ctrl和enter才触发事件执行
【案例应用】:表单输入后按回车键添,按esc则清空表单
<input type="text" v-model="newbrand"
@keyup.enter="add"
@keyup.esc="newbrand=''" />
4. v-model 表单绑定
在不操作 DOM 的前提下,实现表单元素和数据的双向绑定。
v-model 指令的修饰符
修饰符
作用
示例
.number
自动将用户输入值转为 Number
<input v-model.number
=“age” />
.trim
去除首尾空白字符
<input v-model.trim
=“msg” />
.lazy
表单输入后失去焦点时更新页面数据,而非实时更新
<input v-model.lazy
=“msg” />
-
input 输入框
-
type=“text”
-
type=“radio”
-
type=“checkbox”
-
type=“xxxx”
-
-
textarea
-
select
5. 条件渲染指令
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。
v-if 和 v-show
-
v-show
的原理是:动态为元素添加或移除style= " display: none; " 样式,从而控制元素的显示与隐藏。- 如果要频繁的切换元素的显示状态,用 v-show 性能会更好。
-
v-if
的原理是:每次动态创建或移除 DOM 元素,实现元素的显示和隐藏。- 如果在运行时条件很少改变,则使用 v-if 较好。
v-if 指令在使用的时候,有两种方式:
-
直接给定一个布尔值 true 或 false
<p v-if="true">被 v-if 控制的元素</p>
-
给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏
<p v-if="type === 'A'">良好</p>
v-else-if
<div v-if="type === 'A'">优秀</div>
<div v-else-if="type === 'B'">良好</div>
<div v-else-if="type === 'C'">及格</div>
<div v-else>不及格</div>
6. 列表渲染指令
基于一个数组来循环渲染一个列表结构。
v-for
v-for
指令需要使用 item in items
形式的特殊语法
items
是源数据 (待循环) 的数组,而item
被循环的每一项。
【示例】:动态渲染表单数据:
<link rel="stylesheet" href="./lib/bootstrap.css">
<!-- 希望 Vue 能够控制下面的这个 div,帮我们把数据填充到 div 内部 -->
<div id="app">
<table class="table table-bordered table-hover table-striped">
<thead>
<th>索引</th>
<th>Id</th>
<th>姓名</th>
</thead>
<tbody>
<!-- 官方建议:只要用到了 v-for 指令,那么一定要绑定一个 :key 属性 -->
<!-- 而且,尽量把 id 作为 key 的值 -->
<!-- 官方对 key 的值类型,是有要求的:字符串或数字类型 -->
<!-- key 的值是千万不能重复的,否则会终端报错:Duplicate keys detected -->
<tr v-for="(item, index) in list" :key="item.id">
<td>{
{ index }}</td>
<td>{
{ item.id }}</td>
<td>{
{ item.name }}</td>
</tr>
</tbody>
</table>
</div>
使用 key 维护列表的状态
官方推荐, 使用 v-for 指令绑定一个
:key
属性,key的作用是为了高效的更新虚拟DOM。
-
key 的值类型,是有要求的:字符串或数字类型
-
把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)
-
改变 data 顺序,index 会重新排序,所以 index 的值不具有唯一性。
计算属性 computed
实时监听
data 中数据的变化,并return 一个计算后的新值
, 供组件渲染 DOM 时使用。可以被
模板结构
(插值、v-bind ) 或methods
方法使用。
- 但是在某些情况下,我们可能需要对数据进行一些转化后在显示,或者需要将多个数据结合起来进行显示,这时候我们可以使用计算属性。
实例 1:
<div id="app">
<h2>{
{getFullName()}}</h2>
<h2>{
{fullName}}</h2>
</div>
const vm = new Vue({
el: '#app',
data: {
firstName: 'lin',
lastName: 'willen'
},
computed: {
fullName () {
return this.firstName + ' ' + this.lastName;
}
},
// 使用 methods: 每次都会调用方法
methods: {
getFullName () {
return this.firstName + ' ' + this.lastName;
}
}
})
特点:
- 定义的时候,要被定义为 “方法”。
- 在使用计算属性的时候,当普通的属性使用即可
- 实现了代码的复用,只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值。
实例2:
<div id="app">
<h2>总价格:{
{totalPrice}}</h2>
</div>
const vm = new Vue({
el: '#app',
data: {
books:[
{id: 1001, name: 'Unix编程艺术',price: 119},
{id: 1002, name: '代码大全',price: 105},
{id: 1003, name: '深入理解计算机原理',price: 99},
{id: 1004, name: '现代操作系统',price: 109}
]
},
computed: {
totalPrice () {
let totalPrice = 0;
for (let i in this.books) {
totalPrice += this.books[i].price;
}
// 也可以使用 for of
for (let book of this.books) {
totalPrice += book.price;
}
return totalPrice;
}
}
})
计算属性 vs 方法
methods
和computed
看起来都可以实现我们的功能,那么为什么还要多一个计算属性
- methods: 每次使用都会调用方法
- computed:
计算属性会缓存计算的结果
, 不变的情况下只调用一次, 除非原属性发生改变,才会重新调用.
计算属性 vs 侦听器
侧重的应用场景不同侧重的应用场景不同
:
- 计算属性侧重于监听
多个值
的变化,最终计算并返回一个新值
。 - 侦听器侧重于监听单个数据的变化,最终执行
特定的业务处理
,不需要有任何返回值
。
vue组件
什么是组件化开发 ?
根据封装的思想,把页面上可重用的 UI 结构封装为组件,方便项目的开发和维护。
vue 中的组件化开发
- vue 是一个支持组件化开发的前端框架。
- vue 中组件的后缀名是
.vue
组件的构成
每个 .vue 组件都由 3 部分构成,分别是:
-
template
:组件的模板结构,且每个组件中必须包含template模板结构。 -
script
: 组件的 JavaScript 行为 -
style
:组件的样式// 标签上添加 lang=“less” 属性,即可使用 less 语法编写组件的样式
// scoped 防止样式冲突
script 节点:
(1)script 中的 name
节点
- 用来定义组件的名称,调试的时候
可以清晰的区分每个组件
。
(2)script 中的 data
节点
- 组件渲染期间需要用到的数据, data
必须是函数
, 不能直接指向对象数据。
(3)script 中的 methods
节点
- 组件中的事件处理函数(
方法
),必须定义到methods
节点中
注册私有组件
通过 components 注册的是私有子组件,被注册的组件只能用在当前组件中。
1.使用 import 语法导入需要的组件
import Left from '@/components/Left.vue'
2.在 script 标签中使用 components
节点注册组件
<script>
export default {
comments:{
Left
}
}
</script>
3.以标签的形式
使用刚才注册的组件
<template>
<Left></Left>
</template>
注册全局组件
在 vue 项目的
main.js
入口文件中,通过Vue.component()
方法,可以注册全局组件。
注册:
import Vue from 'vue'
import App from './App.vue'
// 导入需要被全局注册的那个组件
import Count from '@/components/Count.vue'
// 参数一: 组件的 '注册名称',将来以标签形式使用时要求和这个名称一样。
// 参数二: 需要被全局注册的那个组件。
Vue.component('MyCount', Count)
// 消息提示的环境配置,设置为开发环境或者生产环境
Vue.config.productionTip = false
new Vue({
// render 函数中,渲染的是哪个 .vue 组件,那么这个组件就叫做 “根组件”
render: h => h(App)
}).$mount('#app')
使用:
<template>
// 这里需要注意 '注册名称'
<MyCount ></MyCount>
</template>
组件注册时名称的大小写
在 Vue 定义组件注册名称的方式有两种:
- 短横线命名法,例如
my-swiper
和my-search
- 使用组件时也必须使用短横线命名
- 大驼峰命名法,例如
MySwiper
和MySearch
- 既可以按照大驼峰命名法使用,也可以
转化为短横线名称
进行使用。
- 既可以按照大驼峰命名法使用,也可以
注意: 在开发中,推荐使用大驼峰命名法
为组件注册名称,因为它的适用性更强。
组件之间的样式冲突问题
默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。
scoped 属性
让当前组件的样式对其子组件是不生效。
Vue 中提供了在style 节点添加 scoped
属性,来防止样式冲突问题:
- 原理是为每个组件分配唯一的自定义属性,在编写组件样式时,通过属性选择器来控制样式的作用域。
<template>
<div class="container" data-v-001>
<h3 data-v-001 > 轮播图组件件</h3>
</div>
</template>
<style>
// 通过中括号'属性选择器',防止样式冲突问题
// 因为每个组件分配的自定义属性是'唯一的'
. container[data-v-001]{
border: 1px solid red;
}
</style>
为了提高开发效率和开发体验,直接在 style 节点使用 scoped 属性:
<style lang="less" scoped>
</style>
/deep/ 样式穿透
让某些样 式对子组件生效。
使用场景: 当使用第三方组件库的时候,需要修改第三方组件默认样式的时候。
<style lang="less" scoped>
/*不加 /deep/ 时,生成的选择器格式为 .title[data-v-052242de]*/
.title{
color: blue;
}
/*加/deep/ 时,生成的选择器格式为 [data-v-052242de] .title*/
/deep/ .title {
color: pink;
}
</style>
Class 与 Style 绑定
通过
v-bind
动态操作元素样式。
1. 动态绑定 HTML 的 class:
通过三元表达式,动态的为元素绑定 class 的类名:
<h3 class="thin" :class="isItalic ?'italic':''">MyDeep 组件</h3>
<button @click="isItalic=!lisItalic"> Toggle Italic </button>
data(){
return { isItalic:true }
.thin{
font-weight:200;
.italic{
font-style:italic;
}
2. 以数组语法绑定 HTML 的 class
如果元素需要动态绑定多个 class 的类名,此时可以使用数组的语法格式
<h3 class="thin":class="[isItalic? 'italic': '',isDelete? 'delete':'']">MyDeep组件</h3>
<button @click="isItalic= !isItalic"> 字体变细 </button>
<button @click="isDelete= !isDelete"> 添加删除线 e</button>
<script>
export default {