0%

Vue学习笔记(一)-初识Vue

1 初识Vue

1.1 Vue安装

安装Vue的方式有很多:

  • 方法一: 直接CDN引入

    <!--开发环境版本,包含了有帮助的命令行警告-->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <!--生产环境版本,优化了尺寸和速度->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  • 方法二:下载和引入
    开发环境 https://vuejs.org/is/vue.js
    生产环境 https://vueis.org/is/vue.min.js

  • 方式三: NPM安装

    稍后详细说明

1.2 Hello Vue

我们来做第一个Vue程序,体验一下Vue的响应式

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>

<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app', // 用于挂载要管理的元素
data: { // 定义数据
message: 'Hello, World!'
}
})
</script>
</body>
</html>

代码做了什么事情?

  • 我们创建了一个Vue对象: app

  • 创建Vue对象的时候,传入了一些options: {}

    • {}中包含了el属性,该属性决定了这个Vue对象挂载到哪个元素上,很明显我们这里是挂载到了id为app的元素上
    • {}中包含了data属性: 该属性会存储一些数据
      - [x] 这些数据可以是我们直接定义出来的,比如上面这样
      - [x] 也可能是来自于网络,从服务器端加载的
  • 浏览器执行代码的流程:
    - [x] 执行到HTML中

    部分显示出对应的HTML
    - [x] 执行到let app = new Vue创建Vue实例,并且对原HTML进行解析和修改

  • 并且我们的代码是响应式的

1.3 Vue列表显示

现在我们展示一个更加复杂的数据: 数据列表

比如我们现在从服务器请求过来一个列表,希望展示到HTML中, 直接上代码:

<div id="app">
<ul v-for="movie in movies"> // 使用v-for指令
<li>{{movie}}</li>
</ul>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app', // 用于挂载要管理的元素
data: { // 定义数据
message: 'Hello, World!',
movies: ['霸王别姬', '肖申克的救赎', '阿甘正传', '星际穿越', '大话西游']
}
})
</script>

使用v-for指令可以简化代码,我们不需要在JavaScript代码中拼接DOM了

而且更重要的是,它还是响应式的。

1.4 v-on指令和methods属性

现在我们实现一个小计数器,点击+计数器j+1,点击-计数器-1

<div id="app">
<h2>当前计数: {{counter}}</h2>
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app', // 用于挂载要管理的元素
data: { // 定义数据
counter: 0
},
methods: {
add() {
this.counter++
},
sub() {
this.counter--
}
}
})
</script>
  • 新的属性: methods,该属性用于在Vue对象中定义方法
  • 新的指令:@click(v-on:click的简写)用于监听某个元素的点击事件,并且制定当发生点击时,执行的方法(通常是methods中定义的方法)

到目前为止我们掌握了这些选项:

  • el

    • 类型: string| HTMLElement
    • 作用:决定之后Vue实例会管理哪个DOM
  • data:
    * 类型: Object| Function
    * 作用: Vue实例对象对应的数据对象

  • methods:
    * 类型:{ [key: string]: Function }
    * 作用:定义属于Vue的一些方法,可以在其他地方调用, 也可以在指令中使用

1.4 v-bind动态绑定style

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 classstyle 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

我们可以传给 v-bind:class 一个对象,以动态地切换 class:

<div v-bind:class="{ active: isActive }"></div>

上面的语法表示 active 这个 class 存在与否将取决于数据属性 isActivetruthiness

你可以在对象中传入更多属性来动态切换多个 class。此外,v-bind:class 指令也可以与普通的 class 属性共存。当有如下模板:

<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>

和如下 data:

data: {
isActive: true,
hasError: false
}

结果渲染为:

<div class="static active"></div>

isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"

绑定的数据对象不必内联定义在模板里:

<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}

需要注意,在模板渲染时vue可能会把固定值解析为变量:

<div id="app">
<p :style="{ fontSize: finalSize + 'px', backgroundColor: 'blue' }"> {{message}}</p>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'aaaaa',
finalSize: 50
}
})

px,默认情况下会被解析为一个变量;如果想确保其被解析为50px,需要在px前后用单引号括起。

1.5 计算属性

1.5.1 使用场景

我们在模板中可以直接通过差值语法显示一些data数据,但是某些情况下,我们可能需要对数据进行一些转化后再显示

  • 比如我们有firstName和lastName两个变量,我们需要展示完整名称
  • 但是如果有多个地方都需要显示完整名称,我们就需要写多个

此时我们可以将上面代码转换成计算属性,如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>{{fullName}}</h2> <!--此处fullName已经作为一个属性值存在-->
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Kobe',
lastName: 'Briant'
},//计算属性
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
<style>
</style>
</body>
</html>

另一个案例,将books中书的总价格动态显示出来:

<div id="app">
<h1 v-for="(book, index) in books">{{index+1}}-{{book.name}}</h1>
<h2>总价格:{{totalPrice}}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{id: 110, name: '深入理解计算机系统', price: 98},
{id: 110, name: 'Unix网络编程', price: 98},
{id: 110, name: 'Python学习手册', price: 98},
{id: 110, name: 'Vue实战指南', price: 98}
]
},//计算属性
computed: {
totalPrice: function () {
let result = 0
for (let i=0; i < this.books.length; i++) {
result += this.books[i].price
}
return result
}
}
})
</script>

1.5.2 set及get方法

计算属性一般是没有set方法的,是只读属性(只有get方法)

data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
computed: {
// 计算属性一般没有set方法,是只读属性
fullName: {
get: function () {
return this.firstName + ' ' + this.lastName
}
}
}

亦可简写成:

computed: {
// 在调用计算属性fullName时,实际上调用的就是fullName的get方法
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}

在某些情况下需要对计算属性的结果重新赋值,则需要手工实现计算属性的set方法:

data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
computed: {
// 计算属性一般没有set方法,是只读属性
fullName: {
set: function(newName){ // 通过set方法将计算属性的显示改成James Lebron: app.fullName='James Lebron'
console.log('-------')
const names = newName.split(' ');
this.firstName = names[0]
this.lastName = names[1]
},
get: function () { // 默认显示Kobe Bryant
return this.firstName + ' ' + this.lastName
}
}
}

1.5.3 计算属性和methods对比

在下面案例中,我们分别用计算属性和methods方法打印fullName, 并且每调用一次打印一条记录,看看分别使用计算属性和methods方法分别要调用相应函数几次:

<div id="app">
<!--通过定义methods-->
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>
<h2>{{getFullName()}}</h2>

<!--通过计算属性-->
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
<h2>{{fullName}}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
methods: {
getFullName() {
console.log('getFullName')
return this.firstName + ' ' + this.lastName
}
},
computed: {
fullName: function () {
console.log('fullName')
return this.firstName + ' ' + this.lastName
}
}
})

得到输出如下:

getFullName
getFullName
getFullName
getFullName
fullName

可以看到同样是显示4次fullname,methods方法调用了4次,而计算属性只调用了一次。

  • 两种方式的最终结果确实是完全相同的。
  • 不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
  • 这就意味着只要 message 还没有发生改变,多次访问 reversedMessage计算属性会立即返回之前的计算结果,而不必再次执行函数

1.6 事件监听

在前端开发中,我们常常和用户交互。

  • 在这个时候,我们就必须监听用户发生的事件,比如点击、拖拽、键盘事件等
  • 在Vue中如何监听事件呢?我们使用v-on指令

v-on介绍

  • 作用:绑定事件监听器
  • 缩写:@
    • 预期:Function | Inline Statement | Object
  • 参数: event

下面我们就具体来学习v-on的使用

<div id="app">
<h2>点击次数:{{counter}}</h2>
<button v-on:click="counter++">+1</button>
<button v-on:click="counter--">-1</button>
</div>

如上,我们可以使用v-on实现了对点击事件的响应

注:v-on有其简写形式,称作语法糖,v-on:click可以简写为***@click***

v-on参数

当通过methods中定义方法,以供**@click**调用的时候,需要注意参数问题:

  • 情况一: 如果该方法不需要额外参数,那么方法后的()可以不添加
    • 但是注意,如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
  • 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件
<div id="app">
<h2>点击次数: {{counter}}</h2>
<button @click="handleAdd">+1</button>
<button @click=handleAddTen(10, $event)>+10</button>
</div>

methods: {
handleAdd(event) {
console.log(event);
this.counter++;
},
handleAddTen(count, event) {
console.log(event);
this.counter += 10;
}
}

.stop修饰符的使用

在某些情况下,我们拿到event的目的可能是进行一些事件的处理

Vue提供了修饰符来帮助我们方便的处理一些事件:

  • .stop - 调用event.stopPropagation()
  • .prevent - 调用event.preventDefault()
  • .(keyCode | keyAlias) - 只当时间是从特定键触发时才触发回调
  • .native - 监听组件根元素的原生事件
  • .once - 只触发一次的回调

例子:

<!-- 1.stop修饰符的使用 -->
<div @click="divclick">
aaaaaa
<button @click.stop="btnClick">按钮</button>
</div>

<!-- 2.prevent修饰符的使用(阻止默认行为) -->
<form action="www.baidu.com">
<input type="submit" value="提交" @click>
</form>

<!-- 3.监听某个键盘的事件 -->
<input type="text" @keyup.enter="keyUp">

<!-- 4.once修饰符的使用(只会触发一次) -->
<button @click.once="doThis"></button>

1.7 条件判断

没啥说的直接代码示例:

<div id="app">
<h2 v-if="score>=90">优秀</h2>
<h2 v-else-if="score>=80">良好</h2>
<h2 v-else-if="score>=60">优秀</h2>
<h2 v-else>不及格</h2>
</div>

一个小案例

<div id="app">
<span v-if="isUser">
<label>用户账号:</label>
<input type="text" id="username" placeholder="用户账号">
</span>
<span v-else>
<label>邮箱地址: </label>
<input type="text" id="email" placeholder="邮箱地址">
</span>
<button @click="handleToggle">切换类型</button>
</div>
  • 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前输入的内容

  • 但是按道理, 我们应该切换到另外一个input元素中了

  • 在另一个input元素中,我们并没有输入内容

  • 为什么会出现这个问题呢

    image-20200104152849954

image-20200104152919080

                            (如图,点击切换类型后输入框中的内容一直存在)

问题解答

  • 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素, 而不是重新创建新的元素
  • 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了

解决方案

  • 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
  • 并且我们需要保证key是不同的

image-20200104153538625

image-20200104153549253

                    (如图,在添加不同key后再次点击切换类型,此时原本input元素中的内容就不会保留了)

v-if 和 v-show在控制元素显示时的区别:

v-if: 当条件为false时,包含v-if指令的元素,根本不会存在于dom中

v-show: 当条件为false时,v-show并不删除元素,只是给我们的元素增加一个行内样式: display: none

1.8 v-for遍历

v-for遍历数组

当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成

  • v-for的语法类似于JavaScript中的for循环
  • 格式如下: item in items的形式

我们来看一个简单的案例:

  • 如果在遍历的过程中不需要使用索引值
    • v-for=”movie in movies”
    • 依次从movies中取出movie,并在元素内容中,我们可以使用Mustache语法,来使用movie
  • 如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢
    • 语法格式: v-for=(item, index) in items
    • 其中的index就代表了取出的item在原数组的索引值

专题:哪些数组的方法是响应式的

  • push方法:在数组后面增加元素

    this.letters.push()

  • pop方法:内删除数组中最后一个元素

    this.letters.pop()

  • shift方法:删除数组中第一个元素

    this.letters.shift()

  • unshift方法:在数组最前面添加元素

  • splice方法:删除元素/插入元素/替换元素

    • 删除元素:第二个参数传入要删除几个元素(如果没有传则删除后面所有元素)

      this.letters.splice(1, 3) # 删除第一个元素后三个元素

    • 替换元素:从第几个元素开始,替换几个元素,分别是什么

      this.letters.splice(1, 3, ‘m’, ‘n’, ‘o’)

    • 插入元素:第二个参数,传入0, 并且后面跟上要插入的元素

      this.letters.splice(1, 0, ‘x’, ‘y’, ‘z’) # 在第一个元素后面插入x, y, z

  • sort方法

    this.letters.sort()

  • reverse方法

    this.letters.reverse()

1.9 补充:高阶函数


三种高阶函数:

  • filter: filter中的回调函数有一个要求,必须返回一个boolean值,
    • 当返回true时, 函数内部自动将这次回调的n加入到新的数组中
    • 当返回false时,函数内部会过滤掉这次的n
const nums = [10, 20, 111, 222, 333, 40, 50]
let newNums = nums.filter(function(n) {
return n < 100
})
console.log(newNums)
newNums2 = nums.filter(n => {
return n < 100
})
console.log(newNums2)
  • map: 对原数组中所有元素执行操作组成一个新的数组
let newNums = nums.map(function(n) {
return n * 2
})
  • reduce: reduce会对数组中所有的内容进程汇总,返回一个值
let total = nums.reduce(function (preValue, n) {  // 前值,当前值
return preValue + n
}, 0) // 第二个参数是初始值

1.10 v-model

表单绑定v-model

  • 表单控件在实际开发中是非常常见的,特别是对于用户信息的提交,需要大量的表单
  • Vue中使用v-model指令来实现表单元素和数据的双向绑定
  • 案例解析
    • 当我们在输入框输入内容时,因为input中v-model绑定了message,所以会实时将输入的内容传递给message,message发生改变
    • 当message发生改变时,因为上面我们使用Mustache语法,将message的值插入到DOM中,所以DOM会发生相应的改变
    • 所以v-model实现了数据的双向绑定
<div id="app">
<input type="text" v-model="message">
<h2>{{ message }}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: "Hello World!"
}

v-model原理

v-model其实是一个语法糖,它背后本质上包含两个操作:

  1. v-bind绑定一个value属性
  2. v-on指令给当前元素绑定input事件

也可以使用v-bind和v-on实现v-model的功能:

<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">

v-model用于radio

设想这样一个场景,在表单提交的过程中需要选择性别,要么男要么女

首先要使两个选项互斥,需要给两个选项指定相同的name:

<div id="app">
<label for="male">
<input type="radio" id="male" name="sex" value="male">
</label>
<label for="female">
<input type="radio" id="female" name="sex" value="female">
</label>
<h2>选择的性别是:{{ sex }}</h2>
</div>

当两个radio指定了相同的name=“sex”时,浏览器认为这两个radio是互斥的,这样在页面上这两个选项只能被选中一个

如果使用v-model处理互斥选项,则不需要指定相同的name=”sex”, 而只需要让这两个radio绑定相同的data即可

<div id="app">
<label for="male">
<input type="radio" id="male" value="male" v-model="sex">
</label>
<label for="female">
<input type="radio" id="female" value="female" v-model="sex">
</label>
<h2>选择的性别是:{{ sex }}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
sex: 'male'
}

如上,只需要将两个radio都指定v-model=”sex”,那么在页面上他们就是互斥的;同时还可以在data中指定初始值sex: ‘male’, 这样在页面上默认的性别值就是male, 体现了Vue数据驱动的特点。

v-model用于checkbox

复选框分为两种情况:单选框和多选框

单个勾选框:

  • v-model即为bool值
  • 吃屎input的value并不影响v-model的值

多个复选框

  • 当是多个复选框时,因为可以选中多个,所以对应的data中的属性时一个数组
  • 当选中某一个时。就会将input的value添加到数组中
<div id="app">
<!-- 单选框 -->
<label for="license">
<input type="checkbox" id="license" v-model="isAgree">同意协议
</label>
<h2>您选择的是:{{ isAgree }}</h2>
<button :disabled="!isAgree">下一步</button>
<hr>
<!--多选框-->
<input type="checkbox" value="唱" v-model="hobbies">
<input type="checkbox" value="跳" v-model="hobbies">
<input type="checkbox" value="rap" v-model="hobbies">rap
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<h2>您的爱好是: {{ hobbies }}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isAgree: false,
hobbies: []
}
})
</script>

v-model用于select

和checkbox一样,select也分为单选和多选的情况

  • 单选:只能选中一个值
    • v-model绑定的是一个值
    • 当我们选中option中的一个时,会将它对应的value赋值到mySelect中
  • 多选:可以选中多个值
    • v-model绑定的是一个数组
    • 当选中多个值时,就会将选中的option对应的value添加到数组中
<div>
<!-- select 选中一个-->
<select name="fruits" v-model="fruit">
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
<option value="peach">桃子</option>
</select>
<h2>您选择的水果是:{{ fruit }}</h2>

<!-- select选中多个 -->
<select name="fruits" v-model="fruits" multiple>
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
<option value="peach">桃子</option>
</select>
<h2>您选择的水果分别是:{{ fruits }}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
fruit: '',
fruits: []
}
})
</script>

也可以用值绑定的方式,直接代码:

<div>
<label v-for="item in balls" :for="item">
<input type="checkbox" :value="item" :id="item" v-model="selectBalls" >{{ item }}
</label>
<h2>您选择的球有: {{ selectBalls }}</h2>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
balls: ['篮球', '足球', '羽毛球', '弹珠球'],
selectBalls: []
}
})
</script>

修饰符

lazy修饰符:

  • 默认情况下, v-model默认是在input事件中同步输入框的数据的。
  • 也就是说,一旦有数据发生改变对应的data 的数据就会自动发生改变。
  • lazy修饰符可以让数据在失去焦点或者回车时才会更新:

number修饰符:

  • 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。

  • 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。

  • number修饰符可以让在输入框中输入的内容自动转成数字类型

trim修饰符:

  • 如果输入的内容首尾有很多空格,通常我们希望将其去除

  • trim修饰符可以过滤内容左右两边的空格

欢迎关注我的其它发布渠道