Evan's blog Evan's blog
首页
关于
  • 分类
  • 标签
  • 归档
  • H5&CSS3
  • JS
  • TS
  • Node
  • Webpack
  • Vue2
  • Vue3
  • 微信小程序
  • Andorid
  • Flutter
推荐
GitHub (opens new window)

conanan

真相只有一个
首页
关于
  • 分类
  • 标签
  • 归档
  • H5&CSS3
  • JS
  • TS
  • Node
  • Webpack
  • Vue2
  • Vue3
  • 微信小程序
  • Andorid
  • Flutter
推荐
GitHub (opens new window)
  • 基础

    • 入门
      • Vue.js 是什么
      • 安装
        • CDN
        • npm
        • CLI
        • Vite
        • 对不同构建版本的解释
      • 计数器
        • 写法1
        • 写法2
        • 写法3
      • options
        • template
        • data
        • methods
        • this 绑定问题 🔥
      • VSCode 代码片段 🔥
      • v-bind 🔥
      • Todo-List 及组件初识
      • 生命周期函数
    • 模版语法&指令
    • 条件渲染&列表渲染
    • 计算属性&侦听器
    • 表单的双向绑定
    • 组件化开发
  • 组件

  • 动画

  • Composition Api

  • 高级语法

  • Vue源码

  • VueCLI&Vite

  • VueRouter

  • Vuex

  • 项目

  • Vue3.x
  • 基础
xugaoyi
2020-12-28
目录

入门

# 入门

代码

配套的代码在 Github (opens new window) 中

# Vue.js 是什么

Vue 是一套用于构建用户界面的渐进式框架(可以只用 Vue,根据后续需要使用其他如 Router、Vuex 等)。

与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

特点如下:

  • 解耦视图和数据
  • 可复用的组件
  • 前端路由
  • 状态管理
  • 虚拟 DOM

# 安装

官方的安装文档 (opens new window)

# CDN

对于制作原型或学习,你可以这样使用最新版本

<script src="https://unpkg.com/vue@next"></script>
1

对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏

# npm

# CLI

# Vite

# 对不同构建版本的解释

在 npm 包的 dist/ 目录 (opens new window)你将会找到很多不同的 Vue.js 构建版本。这里列出了它们之间的差别:

image-20201228002650679

具体见文档 (opens new window)

# 计数器

可以将 template 中内容写到 html 中,Vue2 的 el 已被 mount() 替代:

# 写法1

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app"></div>

    <script>
      const options = {
        // template中写么有提示,不方便。和#app不一样!,不能删掉#app
        template: `
          <button @click="decrement">-</button>
          <span>{{counter}}</span>
          <button @click="increment">+</button>
        `,
        data() {
          return {
            counter: 0,
          }
        },
        methods: {
          decrement() {
            this.counter--
          },
          increment() {
            this.counter++
          },
        },
      }

      // // Vue.createApp 创建 Vue 应用
      // const app = Vue.createApp(options);
      // // mount 装载到哪里,即在 id = root 的 html 中使用 vue
      // const vm = app.mount('#root');

      // 可以链式编程:
      const vm = Vue.createApp(options).mount('#app')
    </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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 写法2

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app"></div>

    <!-- 这种提示也不清晰 -->
    <!-- <script type="x-template" id="temp">
      <button @click="decrement">-</button>
      <span>{{counter}}</span>
      <button @click="increment">+</button>
    </script> -->

    <!-- 推荐 -->
    <template id="temp">
      <button @click="decrement">-</button>
      <span>{{counter}}</span>
      <button @click="increment">+</button>
    </template>

    <script>
      const options = {
        // 和#app不一样!,不能删掉#app
        template: '#temp', //
        data() {
          return {
            counter: 0,
          }
        },
        methods: {
          decrement() {
            this.counter--
          },
          increment() {
            this.counter++
          },
        },
      }

      // // Vue.createApp 创建 Vue 应用
      // const app = Vue.createApp(options);
      // // mount 装载到哪里,即在 id = root 的 html 中使用 vue
      // const vm = app.mount('#root');

      // 可以链式编程:
      const vm = Vue.createApp(options).mount('#app')
    </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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 写法3

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <button @click="decrement">-</button>
      <span>{{counter}}</span>
      <button @click="increment">+</button>
    </div>

    <script>
      const options = {
        // 不写template也可以!
        data() {
          return {
            counter: 0,
          }
        },
        methods: {
          decrement() {
            this.counter--
          },
          increment() {
            this.counter++
          },
        },
      }

      // // Vue.createApp 创建 Vue 应用
      // const app = Vue.createApp(options);
      // // mount 装载到哪里,即在 id = root 的 html 中使用 vue
      // const vm = app.mount('#root');

      // 可以链式编程:
      const vm = Vue.createApp(options).mount('#app')
    </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
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# options

# template

表示的是Vue需要帮助我们渲染的模板信息。

  • 它里面有很多的HTML标签,这些标签会替换掉我们挂载到的元素(比如id为app的div)的innerHTML;模板中有一些奇怪的语法,比如 {{}},比如 @click,这些都是模板特有的语法
  • 如果字符串以 # 开始,则它将被用作 querySelector,并使用匹配元素的 innerHTML 作为模板字符串

有如下几种方式:

  • 直接写template里面,有点过于别扭了,并且IDE很有可能没有任何提示,阻碍我们编程的效率。Vue还提供了两种方式:

  • 使用script标签,并且标记它的类型为 x-template(和layui那种一样),设置id。

    <script type="x-template" id="temp"></script>
    
    template: '#temp', //
    
    1
    2
    3

    注意和mount('#app')不一样!template: '#temp' 会把其内容渲染到 mount 中!

  • 使用任意标签(通常使用template标签,因为不会被浏览器渲染),设置id。🔥

    <template id="temp"></template>
    
    template: '#temp', //
    
    1
    2
    3

    注意和mount('#app')不一样!template: '#temp' 会把其内容渲染到 mount 中!

  • 当然直接写在 mount 的元素中也可以!

# data

传入一个函数,并且该函数需要返回一个对象

  • 在Vue2.x的时候,也可以传入一个对象(虽然官方推荐是一个函数)
  • 在Vue3.x的时候,必须传入一个函数,否则就会直接在浏览器中报错

data 中返回的对象会被Vue的响应式系统劫持,之后对该对象的修改或者访问都会在劫持中被处理

  • 所以我们在template中通过 访问counter,可以从对象中获取到数据
  • 我们修改counter的值时,template中的 也会发生改变;

# methods

methods属性是一个对象,通常我们会在这个对象中定义很多的方法:

  • 这些方法可以被绑定到 template 模板中;
  • 在该方法中,我们可以使用this关键字来直接访问到data中返回的对象的属性

# this 绑定问题 🔥

  • methods 的方法定义为什么不能使用箭头函数(官方文档有给出解释)

  • 不使用箭头函数的情况下,this到底指向的是什么? 是 window

    箭头函数使用this的查找规则,它会在自己的上层作用于中来查找this,最终刚好找到的是script作用于中的this,所以就是window 🔥。

  • vue源码中使用 bind 绑定 publicThis 到每个 method 上,存入 ctx[methos]

# VSCode 代码片段 🔥

  • 第一步,复制自己需要生成代码片段的代码;

  • 第二步,https://snippet-generator.app/在该网站中生成代码片段;

  • 第三步,在VSCode中配置代码片段;

    image-20220113201153379

# v-bind 🔥

  • 一般使用:v-bind:src='src'或简写:src='src'。只能传递单独的值
  • 在封装高级组件时(底层是如Element的组件),可以使用v-bind='info'来传递info对象!

# Todo-List 及组件初识

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World</title>
  </head>
  <body>
    <div id="root">
      <div>
        <input v-model="item" />
        <button @click="handleAddItem" :title="item">添加</button>
        <ul>
          <li v-for="(item,index) in list">
            <todo-item
              :item="item"
              :index="index"
              @handle-delete-item="handleDeleteItem"
            />
          </li>
        </ul>
      </div>
    </div>

    <!-- 组件模版分离 -->
    <template id="todo-item">
      <span>{{index+1}}</span>
      <span>--</span>
      <span>{{item}}</span>
      <button @click="handleDeleteItem(index)">删除</button>
    </template>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
      let options = {
        data() {
          return {
            item: '',
            list: [],
          }
        },
        methods: {
          handleAddItem() {
            this.list.push(this.item)
            this.item = ''
          },
          handleDeleteItem(index) {
            this.list.splice(index, 1)
          },
        },
      }

      // Vue.createApp 创建 Vue 应用,存储到 app 中
      //传入的参数表示,这个应用最外层的组件,该如何展示
      const app = Vue.createApp(options)

      // 组件
      app.component('todo-item', {
        template: `#todo-item`,
        props: {
          item: {
            type: String,
            default: '',
          },
          index: {
            type: Number,
            default: 0,
          },
        },
        emits: ['handle-delete-item'],
        methods: {
          handleDeleteItem(index) {
            this.$emit('handle-delete-item', index)
          },
        },
      })

      // mount 装载到哪里,即在 id = root 的 html 中使用 vue
      // vm 就是 vue 应用的根组件
      // mvvm 模式,m model 数据, v view 视图,vm viewModal视图数据连接层
      const vm = app.mount('#root')

      // 改变数据
      // vm.$data.item = '测试课程'
      // vm.item = '测试课程'
    </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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

# 生命周期函数

注意 Vue2 的 destroy 等已被 unmount 等取代

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World</title>
  </head>
  <body>
    <div id="root">
      <div>{{counter}}</div>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
      // 生命周期函数:在某一刻会自动执行的函数
      // 执行完 Vue.createApp 并且 mount 后开始进行生命周期函数

      let options = {
        data() {
          return {
            counter: 1,
          }
        },
        beforeCreate() {
          console.log(
            '=====[beforeCreate]: after init events & lifecycle。事件绑定、生命周期函数等。即 Vue 应用生成之前,Vue.createApp',
            '。root innerHTML: ',
            document.getElementById('root').innerHTML // 空
          )
        },
        created() {
          console.log(
            '=====[created]: after init injections & reactivity。依赖注入、响应式(数据双向绑定)等。即 Vue 应用生成之后,Vue.createApp',
            '。root innerHTML: ',
            document.getElementById('root').innerHTML // 空
          )
        },
        // 组件中有 template 则编译为 render 函数,没有则使用 mount 挂载的 el DOM 元素作为 template 进行编译
        beforeMount() {
          console.log(
            '=====[beforeMount]: template(或 el) 的 innerHtml 被编译成render函数后。或称为组件被渲染到页面前。app.mount()',
            '。root innerHTML: ',
            document.getElementById('root').innerHTML // 空,此时没有任何内容!
          )
        },
        mounted() {
          console.log(
            '=====[mounted]: after Create app.$el and replace "el" with it。 组件被渲染到页面后。此时页面的所有数据都可以正常展示!!!app.mount()',
            '。root innerHTML: ',
            document.getElementById('root').innerHTML // <div>1</div>
          )
        },
        beforeUpdate() {
          // 执行 vm.counter ++ 改变了 data 中数据即可
          console.log(
            '=====[beforeUpdate]: when data change, before Virtual DOM re-rendered and patch。即 data 变化,且页面重新渲染前执行',
            '。root innerHTML: ',
            document.getElementById('root').innerHTML // <div>1</div>
          )
        },
        updated() {
          // 执行 vm.counter ++ 改变了 data 中数据即可
          console.log(
            '=====[updated]: when data change, after Virtual DOM re-rendered and patch。即 data 变化,且页面重新渲染后执行',
            '。root innerHTML: ',

            document.getElementById('root').innerHTML // <div>2</div>
          )
        },
        beforeUnmount() {
          console.log(
            '=====[beforeUnmount]: when app.unmount() is called。即 Vue 应用失效时,类比 beforeMount',
            '。root innerHTML: ',
            document.getElementById('root').innerHTML // <div>2</div>
          )
        },
        unmounted() {
          console.log(
            '=====[unmounted]: when app.unmount() is called。即 Vue 应用失效,且 DOM 完全销毁之后,类比 mounted',
            '。root innerHTML: ',
            document.getElementById('root').innerHTML // 空
          )
        },
      }

      // Vue.createApp 创建 Vue 应用
      // mount 装载到哪里,即在 id = root 的 html 中使用 vue
      const app = Vue.createApp(options)
      const vm = app.mount('#root')

      // vm.$data.counter = 2
      vm.counter = 2
      // app.unmount()
    </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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

实例的生命周期

编辑 (opens new window)
上次更新: 2022/03/23, 17:55:39
模版语法&指令

模版语法&指令→

最近更新
01
重点
04-12
02
搭建项目
04-04
03
TS补充
03-30
更多文章>
Theme by Vdoing | Copyright © 2019-2022 conanan | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式