唐抉的个人博客

前端框架之Vue.js(一)

字数统计: 3.1k阅读时长: 13 min
2022/11/03

Vue.js基础

Vue是一套用于构建用户界面的渐进式框架。与其他大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,易于上手且便于与第三方库或既有项目结合。

Vue不支持IE8及以下的版本,它支持所有兼容ECMA Script 5的浏览器。

安装

直接用<script>引入

若要在现有站点中使用Vue,可以通过<script>元素在页面中使用。

  • 开发环境版本,包含了有帮助的命令行警告:

    1
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  • 生产环境版本,优化了尺寸和速度。在站点上包含Vue时要指定版本号:

    1
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

使用npm安装

直接用<script>引入vue的方法有一些局限性,若要构建更复杂的应用程序,需要使用npm软件包和脚手架CLI。在此之前,需要安装node.js 8.11及以上的版本,安装有包管理器npm。

在cmd里使用node.js的npm命令安装Vue:

1
npm install vue

在cmd里使用node.js的npm命令安装脚手架CLI:

1
2
3
npm install --global @vue/cli
若安装不上使用下面命令进行安装
cnpm install -g @vue/cli

注意:不推荐新手直接使用vue-cli,尤其是还不熟悉基于Node.js的构建工具时。

Vue Devtools

在使用vue时,推荐在浏览器上安装 Vue Devtools。它允许在一个更友好的界面中审查和调试 Vue 应用。

声明式渲染

Vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM系统。

新建一个html文件,编写以下代码后运行,即可创建第一个Vue应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{message}}
</div>
</body>
<script>
var app=new Vue({
el:'#app',
data:{
message:'Hello Vue!'
}
})
</script>
</html>
<!--运行结果如下:-->
Hello Vue!

创建应用的过程看起来与渲染一个字符串模板类似。现在数据和DOM已经被建立了管理,所有东西都是响应式的。

在运行代码的浏览器上按F12打开开发人员工具,选择控制台(后续简称为JavaScript控制台),修改app.message的值,即可看到浏览器中也会及时更新显示的值:

一个Vue应用会将其挂载到一个DOM元素上(上述代码中是#app),然后对其进行完全控制。

除了文本插值,还可以绑定元素attribute如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{message}}
</div>
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒查看此处动态绑定的提示信息!
</span>
</div>
</body>
<script>
var app=new Vue({
el:'#app',
data:{
message:'Hello Vue!'
}
})
var app2=new Vue({
el:'#app-2',
data:{
message:'页面加载于 '+new Date().toLocaleString()
}
})
</script>
</html>

这里的v-bind attribute被称为指令。指令带有前缀v-以表示它们是Vue提供的特殊attribute。它们会在渲染的DOM上应用特殊的响应式行为。在上述代码中,该实例的意思是:将这个元素节点的title atrribute和Vue实例的message property保持一致。

若再次打开JavaScript控制台,输入app2.message='新消息',就会再次看到这个绑定了title attribute的HTML已经进行了更新。

条件与循环

可以利用条件判断来控制切换一个元素是否显示:

1
2
3
<div id="app-3">
<p v-if="seen">现在你看到我了</p>
</div>
1
2
3
4
5
6
var app3=new Vue({
el:'#app-3',
data:{
seen:true
}
})

若打开JavaScript控制台,输入app3.seen=false,就会再次看到之前显示的消息消失了。

上述例子演示了不仅可以把数据绑定到DOM文本或attribute,还可以绑定到DOM结构。除此之外,Vue也提供了一个强大的过渡效果系统,可以在Vue插入/更新/移除元素时自动应用过渡效果。

还有很多其他指令,每个都有特殊的功能,如v-for指令可以绑定数组的数据来渲染一个项目列表:

1
2
3
4
5
6
7
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{todo.text}}
</li>
</ol>
</div>
1
2
3
4
5
6
7
8
9
10
var app4=new Vue({
el:'#app-4',
data:{
todos:[
{ text:'学习 JavaScript'},
{ text:'学习 Vue'},
{ text:'搞个项目'}
]
}
})

在控制台里,输入app4.todos.push({ text: '新项目'}),会发现列表最后添加了一个新项目。

处理用户输入

为了让用户和应用进行交互,可以用v-on指令添加一个事件监听器,通过它调用在Vue实例中定义的方法:

1
2
3
4
<div id="app-5">
<p>{{message}}</p>
<button v-on:click="reverseMessage">反转信息</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
var app5=new Vue({
el:'#app-5',
data:{
message:'Hello Vue.js!'
},
methods:{
reverseMessage:function(){
this.message=this.message.split('').reverse().join('')
}
}
})

注意:在reverseMessage方法中,虽然更新了应用状态,但没有触碰DOM,所有的DOM操作都有Vue来处理。

Vue还提供了v-model指令,可以实现表单输入和应用状态之间的双向绑定:

1
2
3
4
<div id="app-6">
<p>{{ message}}</p>
<input v-model="message">
</div>
1
2
3
4
5
6
var app6=new Vue({
el:'#app-6',
data:{
message:'Hello Vue!'
}
})

组件化应用创建

组件系统是Vue的另一个重要概念。它是一种抽象,允许使用小型、独立和通常可复用的组件构建大型应用。因此任意类型的应用界面都可以抽象为一个组件树。

在Vue里,一个组件本质上是一个拥有预定义选项的一个Vue实例。其中使用 v-bind 指令将待办项传到循环输出的每个组件中:

1
2
3
4
5
6
7
8
<div id="app-7">
<ol>
<!--使用v-bind指令将待办项传到循环输出的每个组件中-->
<!--为每个todo-item提供todo对象-->
<!--todo对象是变量,其内容是动态的。同时也需要为每个组件提供一个"key"-->
<todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id"></todo-item>
</ol>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
Vue.component('todo-item',{
//todo-item组件接收一个名为todo的prop,类似于一个自定义attribute
props:['todo'],
template:'<li>{{todo.text}}</li>'
})
var app7=new Vue({
el:'#app-7',
data:{
groceryList:[
{ id:0,text:'蔬菜'},
{ id:1,text:'奶酪'},
{ id:2,text:'薯条'}
]
}
})
</script>

上述代码中,将应用分割成了两个更小的单元。子单元通过prop接口与负担也进行了良好的解耦,后续可以进一步改进<todo-item>组件,提供更为复杂的模板和逻辑,而不会影响到父单元。在一个大型应用中,将整个应用程序划分为组件是有必要的。

组件与自定义元素的关系

Vue组件是Web组件规范的一部分,其与自定义元素十分类似,但还是有关键的差别:

  • Web Components规范已完成并通过,但未被所有浏览器原生实现。相比之下,Vue组件不需要任何polyfill,且在所有支持的浏览器中表现一致。必要时,Vue组件也可以包装与原生自定义元素之内
  • Vue组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流、自定义事件通信以及构建工具集成。

因此,虽然Vue内部没有使用自定义元素,但在应用使用自定义元素或以自定义元素发布时,仍然有着很好的操作性。Vue CLI脚手架 也支持将Vue组件构建成为原生的自定义元素。

Vue实例

创建一个Vue实例

每个Vue应用都是通过用Vue函数创建一个新的Vue实例开始的:

1
2
3
var vm=new Vue({
//选项
})

在文档中经常会使用vm这个变量名表示Vue实例。当创建一个实例时,可以传入一个选项对象。

一个Vue应用由一个通过new Vue创建的根Vue实例,以及可选的嵌套的、可复用的组件树组成。所有的Vue组件都是Vue实例,并且接受相同的选项对象。

数据与方法

当一个Vue实例被创建时,它将data对象中的所有property加入到Vue的响应式系统中。当这些property的值发生改变时,视图将会产生响应, 即匹配更新为新的值。

1
2
3
4
5
6
7
8
9
10
11
12
   var data={a:1}//数据对象
var vm=new Vue({//该对象被加入到一个Vue实例中
data:data
})
//获得这个实例上的property,返回源数据中对应的字段
vm.a==data.a
//设置property会影响到原始数据
vm.a=2
data.a//返回2
//反过来也一样
data.a=3
vm.a//返回3

当这些数据改变时,视图会进行重渲染。只有当实例被创建时就已经存在与property才是响应式的。若后面才添加一个新的property

1
vm.b='h1'

那么对b的改动将不会触发任何视图的更新。若是知道后续是需要一个property,但一开始时它为空或不存在,则需要设置一些初始值以保证视图能同步更新:

1
2
3
4
5
6
7
data{
newTodoText:'',
visitVount:0,
hideCompletedTodos:false,
todos:[],
error:null
}

使用Object.freeze()会阻止修改现有的property,也意味着响应系统无法再追踪其变化:

1
2
3
4
5
<div id="app-8">
<p>{{foo}}</p>
<!--这里的foo不会更新!-->
<button v-on:click="foo = 'baz'">Change it </button>
</div>
1
2
3
4
5
6
7
8
9
 var obj={
foo:'bar'
}
Object.freeze(obj)

var app8=new Vue({
el:'#app-8',
data:obj
})

除了数据property,Vue实例还暴露了一些有用的实例property与方法。它们都有前缀$,以便与用户定义的property区分开来:

1
2
3
4
5
6
vm.$data===data//返回true
vm.$el===document.getElementById('example')//返回true
$watch是一个实例方法
vm.$watch('a',function(newValue,oldValue){
//这个回调将在'vm.a'改变后调用
})

实例生命周期钩子

每个Vue实例在被创建时都要经过一系列的初始化过程,如设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新DOM等。同时在这个过程中也会运行一些名为生命周期钩子的函数。

created钩子可以用来在一个实例被创建之后执行代码:

1
2
3
4
5
6
7
8
9
    new Vue({
data:{
a:1
},
created:function(){
console.log('a is: '+this.a)
}
})
//返回a is: 1

也有一些其他的钩子,在实例生命周期的不同阶段被调用,如mountedupdateddestroyed。生命周期钩子的this上下文指向调用它的Vue实例。

注意:不要在选项property或回调上使用箭头函数,如created:()=>console.log(this.a)或是vm.$watch('a',newValue=>this.myMethod())。因为箭头函数并没有thisthis作为变量一直向上级词法作用域查找,直至找到为止,经常会报错。

生命周期图示

CATALOG
  1. 1. Vue.js基础
    1. 1.1. 安装
      1. 1.1.1. 直接用<script>引入
      2. 1.1.2. 使用npm安装
      3. 1.1.3. Vue Devtools
    2. 1.2. 声明式渲染
    3. 1.3. 条件与循环
    4. 1.4. 处理用户输入
    5. 1.5. 组件化应用创建
      1. 1.5.1. 组件与自定义元素的关系
    6. 1.6. Vue实例
      1. 1.6.1. 创建一个Vue实例
        1. 1.6.1.1. 数据与方法
      2. 1.6.2. 实例生命周期钩子
      3. 1.6.3. 生命周期图示