介绍
提示
已经了解Vue2且仅想知道Vue3有哪些新功能?请参阅迁移指南
Vue.js是什么?
Vue(读音/vjuː/,像view一样发音)是一套用于构建用户界面的先进框架,不像其他僵化的框架,Vue被设计为全面的渐进式可扩没用框架。该核心库只关注视图层,使用非常简单且易于与其他第三方类库或现有项目进行集成。另一方面当与现代化工具以及支持类库结合使用时,Vue也完全能够为复杂的单页面应用(SPA)提供完美支持。
开始使用
提示
官方手册认为HTML,Css,JavaScript你已达到中等水平。如果你是前端开发的新手,直接跳过基础学习Vue框架不是一个好主意,建议掌握基础知识以后再回来!了解其他框架对学习Vue有帮助,但也不是必须的。
最佳学习习Vue.js方法是验证使用Hello World示例。可以在新标签打开这个链接,跟着我们一起学习这些基础示例。
安装节已提供了多种安装Vue的方式。说明:不推荐初学者一开始就使用vue-cli
,特别是你对基于Node.js构建工具不是非常熟悉的情况下。
声明式渲染
Vue.js的核心是让我们很简单的使用模板语法声明式渲染数据至DOM元素上。
完整代码如下:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="counter">
Counter:{{counter}} <br />
</div>
</body>
<script type="text/javascript">
const Counter = {
data() {
return {
counter: 0
}
}
}
Vue.createApp(Counter).mount("#counter")
</script>
</html>
运行结果如下:
我们已成功创建第一个Vue应用!这看起来跟渲染一个字符模板非常相似,但Vue在后台做了大量的工作。数据和DOM元素建立起了关联,并且所有都是响应式的。我们怎么知道是响应式的?看看下面这个例子,counter
这个变量每秒增加,你将会看到界面上的DOM元素是如何变化的!
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
Counter:{{counter}} <br />
</div>
</body>
<script type="text/javascript">
const Counter = {
data() {
return {
counter: 0
}
},
mounted() {
setInterval(() => {
this.counter++
}, 1000)
}
}
Vue.createApp(Counter).mount("#app")
</script>
</html>
除了文本插值,可以像这样绑定元素属性:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<span v-bind:title="message">
鼠标放到我上面,将会看到动态绑定的title信息
</span>
</div>
</body>
<script type="text/javascript">
const Counter = {
data() {
return {
message: "页面载入时间为:"+ new Date().toLocaleString()
}
}
}
Vue.createApp(Counter).mount("#app")
</script>
</html>
我们学习到了一些新的东西。你看到的v-bind
属性我们称之为指令。指令是以v-
打头表明是由Vue提供的特殊属性,你可能已经猜到了,他们可以响应式的渲染DOM。这里我们基本上可以说“这个实例是通过message
这个变量动态的绑定到了html元素上”。
处理用户输入
为了让用户和界面进行交互,我们可以使用v-on
指令绑定一个事件监听,调用在当前实例中定义的方法:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<span v-bind:title="message">
{{message}}
<br />
<button v-on:click="reverseMessage">反转上文字</button>
</span>
</div>
</body>
<script type="text/javascript">
const Counter = {
data() {
return {
title: "页面载入时间为:"+ new Date().toLocaleString(),
message: "鼠标放到我上面,将会看到动态绑定的title信息"
}
},
methods: {
reverseMessage() {
this.message = this.message.split('').reverse().join('')
}
}
}
Vue.createApp(Counter).mount("#app")
</script>
</html>
点击按钮后,message内容被反转为:
注意这个方法没有使用DOM就更新了界面上的内容 - 所有DOM都由Vue进行操作,而你的代码只要关注具体的业务逻辑即可。
同时Vue提供了v-model指令,可以轻而易举的实现表单文本框和界面元素(app state)的双向绑定:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<p>{{ message }} </p>
<input v-model="message" />
</div>
</body>
<script type="text/javascript">
const Counter = {
data() {
return {
message: "你好世界!"
}
},
}
Vue.createApp(Counter).mount("#app")
</script>
</html>
(你可以想象一下,用jquery,你需要多少行代码来实现双向绑定?其实我不是黑jquery,当年jquery节省了我们大量时间调浏览器兼容性和可以调用一些强大的方法)
条件分支及循环
非常容易切换一个元素的显示状态:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<span v-if="seen">看的见我?看不见我?</span>
</div>
</body>
<script type="text/javascript">
const Counter = {
data() {
return {
seen: true
}
},
}
Vue.createApp(Counter).mount("#app")
</script>
</html>
(只需要控制seen变量为true或false就能显示/隐藏span标签)
这个示例演示了DOM元素不仅能绑定字符和属性,同时也可以绑定DOM结构(控制DOM的展示?),另外,Vue提供了强大的转场效果系统,当我们在界面上插入/更新/移除元素时会自动应用转场效果。
还有很多其他指令,每个都有自己独特的功能。例如v-for
指令可以将一个数组的每个元素展示成一个列表:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in todos">
{{ item.week }} : {{ item.text }}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
const app = {
data() {
return {
todos: [
{"week":"周一","text":"学习java"},
{"week":"周二","text":"学习oracle"},
{"week":"周三","text":"学习python"},
{"week":"周四","text":"学习uni-app"},
{"week":"周五","text":"看电影"},
{"week":"周六","text":"休息"},
{"week":"周日","text":"休息"}
]
}
},
}
Vue.createApp(app).mount("#app")
</script>
</html>
运行结果如下:
组件化
组件系统是Vue中另一个非常重要的概念,因为是一种抽像,允许我们使用小型 、自包含、可反复使用的组件构建大型应用。如果我们仔细想一想,几乎所有的用户界面都可以抽像成一个组件树。
Vue中,组件本质上是拥有预定义选项的实例。Vue中注册组件也很简单:像应创建应用对象一样创建组件,然后在父页面中components
选项中进行定义 :
//js
// 创建Vue应用
const app = Vue.createApp(...)
// Define a new component called todo-item
app.component('todo-item', {
template: `<li>This is a todo</li>`
})
// 挂载Vue应用
app.mount(...)
现在你就可以在其他页面的模板中调用这个组件了
<ol>
<!-- 创建一个todo-item组件的实例 -->
<todo-item></todo-item>
</ol>
但这样每个todo渲染的文字内容都是一样的,没有意思。我们可以从父页面传递数据到子组件。接下来让我们改造下组件定义来接收一个prop:
app.component('todo-item', {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`
})
然后我们在使用组件的地方可以传递不同的todo参数:
<div id="todo-list-app">
<ol>
<!--
现在我们提供含有todo-item的todo对象变量,
这意味着组件内容是动态变化的。
我们同时需要为每个组件指定一个“key”,后面再做解释。
-->
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id"
></todo-item>
</ol>
</div>
const TodoList = {
data() {
return {
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '芝士' },
{ id: 2, text: '任何人类能吃的食品 }
]
}
}
}
const app = Vue.createApp(TodoList)
app.component('todo-item', {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`
})
app.mount('#todo-list-app')
看一个完整的例子:
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>vue demo1</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<ul>
<todo-item
v-for="(item,index) in todos"
v-bind:todo="item"
v-bind:key="index"
></todo-item>
</ul>
</div>
</body>
<script type="text/javascript">
const todoList = {
data() {
return {
todos: [
{"week":"周一","text":"学习java"},
{"week":"周二","text":"学习oracle"},
{"week":"周三","text":"学习python"},
{"week":"周四","text":"学习uni-app"},
{"week":"周五","text":"看电影"},
{"week":"周六","text":"休息"},
{"week":"周日","text":"休息"}
]
}
}
}
const app = Vue.createApp(todoList)
app.component('todo-item',{
props: ['todo'],
template: '<li>{{todo.week}}:{{todo.text}}</li>'
})
app.mount("#app")
</script>
</html>
这是一个非预想中的示例,但是我们已将应用分隔成两个单元,且父应用通过props接口合乎逻辑的分隔出了一个子组件,我们可以进一步的完善<todo-item>
组件实现复杂的模板和逻辑而不影响父应用。
在大型应用中,有必要将整个应用分割成不同的组件使得开发更加便于管理。在后续章节中我们会更多的谈到组件,下面简单演示一个(想像)示例展示组件是如何在模板中使用的:
<div id="app">
<app-nav></app-nav>
<app-view>
<app-sidebar></app-sidebar>
<app-content></app-content>
</app-view>
</div>
关于自定义标签
你可能已经注意到了,Vue组件和HTML的自定义标签非常像,属于Web 组件规则的一部分。这是因为Vue组件语法比Web组件规则更加宽松的模型。举个例子,Vue组件实现了插槽API和特殊属性。但是仍然有一些不同点:
- WEB组件已经被确定但不是所有浏览器能原生支持。Safari 10.1+,Chrome 54+ 和Firefox 63+ 原生已支持WEB组件。相对而言,Vue组件一如既往的在所有支持的浏览器中均能工作(兼容IE11及以上)。如果有必要,Vue组件还可以放置进一个原生的标签中。
- Vue组件提供了简单的定制标签提不具备的功能,突出的包括组件间数据流,标准事件通信以及构建工具集成。
即便Vue内部并不使用定制标签,但在使用和发布自定义标签时仍然具备很强的互操作性。Vue CLI同时也提供将Vue组件注册为原生自定义标签的支持。
准备好了吗?
我们已经对Vue.js核心功能做了简要的介绍 - 手册的剩余部分,我们将再次详细介绍并包含很多高级功能点和细节,所以,请务必通读该教程!