# Vue2教程 - 3 HelloWorld

下面正式进入 Vue 的学习。

首先创建一个 Vue 的项目,前面讲了 Vue 有三种安装方式,如果你的项目中部分页面使用 Vue,那么你直接在你的页面引入 vue 的脚本就可以了,就不用创建 Vue 项目了,如果从0开始创建 Vue 项目,那就按照下面的一步步来。

# 3.1 创建项目

在开发环境搭建章节,已经安装了 Nodejsvue-cli,下面使用 vue-cli 来创建 Vue 项目。

有两种创建方式:

  • 使用 vue ui
  • 使用命令行

# 3.1.1 使用vue ui创建项目

# 1 运行vue ui

在命令行运行 vue ui 指令

# 在命令行运行
vue ui
1
2

我在运行 vue ui 命令还遇到一个错误,真是出师未捷身先死,服了:

ERROR  Failed to get response from https://registry.npm.taobao.org/vue-cli-version-marker
1

Windows系统解决方法

找到你的用户下的 .vuerc 文件:C:\Users\xxxx\.vuerc ,这里根据自己的用户名更改 然后改为:

{ "useTaobaoRegistry": false, "packageManager": "npm" }
1

Mac或Linux解决方法:

# 编辑用户目录下的.vuerc文件
vim ~/.vuerc
1
2

useTaobaoRegistry 改为 false

{
  "useTaobaoRegistry": false 
}
1
2
3

运行 vue ui 完成,会为我们打开一个 http://localhost:8080/ 的页面:

# 2 创建项目

我们将在这个页面完成Vue项目的新建。然后切换到创建,选择项目所在的目录,待会将在该目录下创建:

然后点击按钮在此创建新项目下一步中,输入项目名称,其他可以不用改。

点击下一步,选择手动

再点击下一步,使用默认选择就可以,不用勾选 RouterVuex ,后面项目需要再配置:

Babel 是用于将 ES6 等现代JavaScript代码转译为向后兼容的JavaScript代码,选中。

Linter/Formatter 是做代码格式校验的,实际开发的时候勾选,这里随意。

下一步,选择 Vue2,然后点击创建项目

点击创建项目,然后弹窗中选择按钮创建项目,不保存预设,就进入项目创建啦。

稍等片刻之后,项目就初始化完成了。上面的步骤中,我们创建了一个vue项目。

# 3.1.2 使用命令行创建项目

首先使用命令行进入某个目录,准备在这个目录下创建项目。

然后执行指令:

下面的指令将在当前目录下创建一个hello-vue的项目

vue create hello-vue
1

出现如下选择, 我们选择使用手动的方式进行创建,如果你选择 Default([Vue2] babel, eslint) 使用默认配置创建也行:

下面是选择一些依赖的组件,按空格来选中和取消,选择完成,回车即可:

Babel 是用于将ES6等现代JavaScript代码转译为向后兼容的JavaScript代码,选中。

Linter/Formatter 是做代码格式校验的,实际开发的时候勾选,这里随意。

选择 Vue 的版本

Where do you prefer placing config for Babel, ESLint, etc.?” 这个选项意味着Babel、ESLint等工具的配置文件将被放置在项目根目录下的单独文件中,如.babelrc.eslintrc等。这样做的好处是配置文件清晰、易于管理。

最后,不将配置保存为模板,选择 N,开始创建项目:

开始创建项目:

稍等片刻之后,项目会创建完成。

# 3.1.3 导入到开发工具

创建完项目,我们可以使用Visual Studio Code打开项目。

# 1 项目结构

项目的结构如下:

在 src 下还有一个非常重要的文件 main.js ,它是Vue.js应用程序的入口文件,负责创建一个Vue根实例,这是Vue应用程序的起点。

# 2 运行项目

使用 ctrl + 1左边的键,打开 VSCode 终端,输入如下命令运行项目:

# 安装项目依赖
npm install

# 运行项目
npm run serve
1
2
3
4
5

终端会有访问首页的地址提示,访问效果如下:

# 3.2 编写HelloWorld

# 1 调整项目结构

src 下的 assetscomponentsApp.vue 删掉:

# 2 编写第一个组件

重新在 src 下创建一个 App.vue 文件,内容如下:

<!-- 结构 -->
<template>
  <div id="root">
    {{ msg }}
  </div>
</template>

<!-- 脚本 -->
<script>
export default {
  name: 'App',
  data() {
    return {
      msg: 'Hello World!'
    }
  },
}
</script>

<!-- 样式,scoped表示样式只对当前组件生效-->
<style scoped>
#root {
  color: red;
}
</style>
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

在 Vue 中,*.vue 文件的内容主要分为三部分:<template><script><style> ,分别对应组件的模板结构、脚本和样式。

  1. <template>

<template> 用来定义 HTML 模板结构,当然会有一些 Vue 相关的指令。在 Vue2 中 <template> 中只能有一个根元素,其他的内容要在这个根元素中。在上面的代码中,使用插值表达式 读取 msg 的值,这 msg 的值哪来的?是下面脚本代码返回的。

  1. <script>

<script> 用来定义组件的脚本,如JavaScript。这些脚本可以在网页加载时执行,也可以在用户与页面交互时执行。

在上面脚本中使用 export default 导出组件,在组件中定义了namedata 选项,name 是组件的名称,data 是一个函数,返回一个对象,返回的是组件的数据,可以在模板结构中使用。上面 HTML 中使用差值表达式读取的就是这里返回的对象的值,通过属性 "msg" 读取。

  1. <style>

<style> 用来定义组件样式,没什么可说的,编写 CSS 样式就可以,scoped 表示样式只对当前组件生效。

当然 Vue 还支持 CSS 预处理器,如 Sass、Less 等,不过需要安装对应的 loader 和依赖包。

# 3 运行项目

使用 npm run serve 运行项目,访问项目结果如下:

# 3.3 解释一下HelloWorld

项目运行,会首先运行 main.js

import Vue from 'vue'
import App from './App.vue'

// 启动生产版本时不显示由Vue在控制台输出的生产提示信息
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
1
2
3
4
5
6
7
8
9

首先引入 Vue 和 App.vue 中创建的 App组件,然后 new Vue() 创建一个 Vue 实例对象,并使用 App 组件创建虚拟节点,作为根节点,挂载到 idapp 的DOM元素上。

idapp 的DOM元素在哪呢?

就在项目的 index.html 中:

<!DOCTYPE html>
<html lang="">
  <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">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
      
    <!-- 这里!!! -->
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

所以最终会将 App.vue 中定义的组件渲染到 <div id="app"></div> 中。

# 3.4 独立安装方式的HelloWorld

如果使用独立方式安装或使用CDN方式使用 Vue,那么只需要在页面引入 Vue 脚本文件即可。

例如我创建一个普通的 HTML 文件,index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  
    <!-- 1.引入Vue -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>

  <!-- 2.将来Vue实例,会控制这个app元素中的所有内容 -->
  <div id="app">
    <p>{{ msg }}</p>
  </div>

  <script>
    // 3.创建一个Vue的实例
    var vm = new Vue({
      el: '#app',  // 表示,当前我们new的这个Vue实例,要控制页面上的哪个区域
      data: { // data 属性中页面要用到的数据
        msg: 'Hello World' // 通过Vue提供的指令,很方便的就能把数据渲染到页面上,程序员不再手动操作DOM元素了
      }
    })
  </script>
    
</body>
</html>
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

在 Vue 实例 data 中定义的数据,可以直接在页面中通过 Vue 指令使用。

直接通过浏览器打开页面,显示HelloWorld。

# 3.5 el与data的两种写法

刚才在上面通过实现 HelloWorld 和 独立安装的方式实现 HelloWorld,可以看到将组件挂载到 <div id="app"> 有两种方式。

  • 方式一: new Vue().$mount('#app') 使用 $mount 函数挂载。

  • 方式二:在 Vue 实例上使用 el 属性声明。

上面这两种方式都可以,但是如果项目整体使用 Vue 搭建,都使用方式一。


同时还看到 data 定义的方式也不一样:

// 方式1:函数式
data() {
  return {
    msg: 'Hello World!'
  }
}

// 方式2:对象式
data: {
  msg: 'Hello World'
}
1
2
3
4
5
6
7
8
9
10
11

现在用哪种方式都可以,但是后面学习到组件,data必须使用函数式,否则会报错。

所以建议 data 一直使用函数式。

# 3.6 MVVM模式与Vue

MVVM(Model-View-ViewModel)是一种软件架构模式,常用于构建用户界面的应用程序。它将应用程序的UI(用户界面)代码与业务逻辑代码分离,从而提高代码的可维护性和可测试性。

MVVM模式的三个主要组成部分:

  1. Model(模型)

    表示应用程序的数据和业务逻辑。它只负责处理和管理数据,不关心用户界面如何展示这些数据。

  2. View(视图)

    用户界面层,负责数据的展示,并将用户输入的数据传递给ViewModel。

  3. ViewModel(视图模型)

    介于Model和View之间的桥梁,它从Model获取数据,并将数据提供给View。同时,它将用户在View上的操作转换为对Model数据的操作。ViewModel是MVVM模式的核心,它实现了视图和模型之间的双向绑定,即当模型数据变化时,视图会自动更新;当视图变化(如用户输入)时,模型数据也会相应更新,不需要手动修改DOM。

Vue.js 完全遵循 MVVM 架构模式,在 Vue 中,将数据定义在组件的 data 函数中,Vue的模板(template)部分充当了视图的角色。Vue使用基于 HTML 的模板语法,通过模板语法,Vue 可以将数据动态地渲染到HTML中。ViewModel 的角色是由Vue实例本身来承担的。Vue实例负责监听数据的变化,并当数据变化时更新视图。同时,Vue 实例也提供了方法(methods)和计算属性(computed properties)等,使得开发者可以在不直接操作 DOM 的情况下,处理用户的输入和复杂的数据逻辑。