# 一.vue 简介

# 1.VScode 中 Vue 插件

  • Vue 3 Snippets https://marketplace.visualstudio.com/items?itemName=hollowtree.vue-snippets
  • Vetur https://marketplace.visualstudio.com/items?itemName=octref.vetur

# 2.什么是 vue

官方给出的概念:Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的前端框架。

  1. 构建用户界面
    • 用 vue 往 html 页面中填充数据,非常的方便
  2. 框架
    • 框架是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能!
    • 要学习 vue,就是在学习 vue 框架中规定的用法!
    • vue 的指令、组件(是对 UI 结构的复用)、路由、Vuex、vue 组件库
    • 只有把上面罗列的内容掌握以后,才有开发 vue 项目的能力!

# 3.vue 的两个特性

  1. 数据驱动视图:

    • 数据的变化会驱动视图自动更新
    • 好处:程序员只管把数据维护好,那么页面结构会被 vue 自动渲染出来!
  2. 双向数据绑定:

    在网页中,form 表单负责采集数据,Ajax 负责提交数据

    • js 数据的变化,会被自动渲染到页面上
    • 页面上表单采集的数据发生变化的时候,会被 vue 自动获取到,并更新到 js 数据中

注意:数据驱动视图和双向数据绑定的底层原理是 MVVM(Mode 数据源、View 视图、ViewModel 就是 vue 的实例)

# 4.MVVM

MVVM 是 vue 实现数据驱动视图和双向数据绑定的核心原理。MVVM 指的是 Model、View 和 ViewModel,

它把每个 HTML 页面都拆分成了这三个部分,如图所示:

image-20230701113255174

在 MVVM 概念中:

  • Model 表示当前页面渲染时所依赖的数据源。
  • View 表示当前页面所渲染的 DOM 结构。
  • ViewModel 表示 vue 的实例,它是 MVVM 的核心。

# 5.MVVM 原理

ViewModel 作为 MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起。

image-20230701113327575

当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构

当表单元素的值发生变化时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到 Model 数据源中

# 6.vue 的版本

当前,vue 共有 3 个大版本,其中:

2.x 版本的 vue 是目前企业级项目开发中的主流版本

3.x 版本的 vue 于 2020-09-19 发布,生态还不完善,尚未在企业级项目开发中普及和推广

1.x 版本的 vue 几乎被淘汰,不再建议学习与使用

总结:

3.x 版本的 vue 是未来企业级项目开发的趋势;

2.x 版本的 vue 在未来(1 ~ 2 年内)会被逐渐淘汰;

# 二.vue 基本使用

# 1.使用步骤

① 导入 vue.js 的 script 脚本文件

② 在页面中声明一个将要被 vue 所控制的 DOM 区域

③ 创建 vm 实例对象(vue 实例对象)

<body>
  <!-- 希望 Vue 能够控制下面的这个 div,帮我们在把数据填充到 div 内部 -->
  <div id="app">{{ username }}</div>

  <!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
  <script src="./lib/vue-2.6.12.js"></script>
  <!-- 2. 创建 Vue 的实例对象 -->
  <script>
    // 创建 Vue 的实例对象
    const vm = new Vue({
      // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
      el: "#app",
      // data 对象就是要渲染到页面上的数据
      data: {
        username: "zhangsan",
      },
    });
  </script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 2.代码和 MVVM

image-20230701113607155

# 三.vue 调试工具

# 1.vue-devtools

安装 vue-devtools 调试工具

vue 官方提供的 vue-devtools 调试工具,能够方便开发者对 vue 项目进行调试与开发。

Chrome 浏览器在线安装 vue-devtools :

https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd

FireFox 浏览器在线安装 vue-devtools :

https://addons.mozilla.org/zh-CN/firefox/addon/vue-js-devtools/

# 2.配置

配置 Chrome 浏览器中的 vue-devtools

点击 Chrome 浏览器右上角的 按钮,选择更多工具 -> 扩展程序 -> Vue.js devtools 详细信息,并勾选如下

的两个选项:

image-20230701113742521

# 3.使用 vue-devtools

在浏览器中访问一个使用了 vue 的页面,打开浏览器的开发者工具,切换到 Vue 面板,即可使用 vue-devtools

调试当前的页面。

image-20230701113833074

# 四.vue 指令

# 1.指令的概念

指令(Directives)是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。

vue 中的指令按照不同的用途可以分为如下 6 大类:

  • ① 内容渲染指令
  • ② 属性绑定指令
  • ③ 事件绑定指令
  • ④ 双向绑定指令
  • ⑤ 条件渲染指令
  • ⑥ 列表渲染指令

注意:指令是 vue 开发中最基础、最常用、最简单的知识点。

# 2.内容渲染指令

  1. v-text 指令的缺点:会覆盖元素内部原有的内容!
  2. 插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容!
  3. v-html 指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!
<div v-text="info"></div>
<div>{{ info }}</div>
<div v-html="info"></div>
1
2
3

# 3.v-bind 属性绑定指令

如果需要为元素的属性动态绑定属性值,则需要用到 v-bind 属性绑定指令。

注意:插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!

  • 在 vue 中,可以使用 v-bind: 指令,为元素的属性动态绑定值;

  • 简写是英文的 :

  • 在使用 v-bind 属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号,例如:

    <div v-bind:title="'box' + index">这是一个 div</div>
    <div :title="'box' + index">这是一个 div</div>
    
    1
    2

使用JavaScript表达式

在 vue 提供的模板渲染语法中,除了支持绑定简单的数据值之外,还支持 Javascript 表达式的运算,例如

<div>1 + 2 的结果是:{{ 1 + 2 }}</div>
<div>{{ tips }} 反转的结果是:{{ tips.split('').reverse().join('') }}</div>
<div :title="'box' + index">这是一个 div</div>
1
2
3
<body>
  <!-- 希望 Vue 能够控制下面的这个 div,帮我们在把数据填充到 div 内部 -->
  <div id="app">
    <input type="text" :placeholder="tips" />
    <hr />
    <!-- vue 规定 v-bind: 指令可以简写为 : -->
    <img :src="photo" alt="" style="width: 150px" />

    <hr />
    <div>1 + 2 的结果是:{{ 1 + 2 }}</div>
    <div>{{ tips }} 反转的结果是:{{ tips.split('').reverse().join('') }}</div>
    <div :title="'box' + index">这是一个 div</div>
  </div>

  <!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
  <script src="./lib/vue-2.6.12.js"></script>
  <!-- 2. 创建 Vue 的实例对象 -->
  <script>
    // 创建 Vue 的实例对象
    const vm = new Vue({
      // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
      el: "#app",
      // data 对象就是要渲染到页面上的数据
      data: {
        tips: "请输入用户名",
        photo: "https://cn.vuejs.org/images/logo.svg",
        index: 3,
      },
    });
  </script>
</body>
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

# 4.v-on 事件绑定指令

vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听。语法格式如下:

<h3>count的值为:{{count}}</h3>
<!--语法格式为v-on:事件名称=“事件处理函数的名称"-->
<button v-on:click="addCount">+1</button>
1
2
3

注意:原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后,

分别为:v-on:click、v-on:input、v-on:keyup

<body>
  <!-- 希望 Vue 能够控制下面的这个 div,帮我们在把数据填充到 div 内部 -->
  <div id="app">
    <p>count 的值是:{{ count }}</p>
    <!-- 在绑定事件处理函数的时候,可以使用 () 传递参数 -->
    <!-- v-on: 指令可以被简写为 @ -->
    <button @click="add(1)">+1</button>
    <button @click="sub">-1</button>
  </div>

  <!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
  <script src="./lib/vue-2.6.12.js"></script>
  <!-- 2. 创建 Vue 的实例对象 -->
  <script>
    // 创建 Vue 的实例对象
    const vm = new Vue({
      // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
      el: "#app",
      // data 对象就是要渲染到页面上的数据
      data: {
        count: 0,
      },
      // methods 的作用,就是定义事件的处理函数
      methods: {
        add(n) {
          // 在 methods 处理函数中,this 就是 new 出来的 vm 实例对象
          // console.log(vm === this)
          console.log(vm);
          // vm.count += 1
          this.count += n;
        },
        sub() {
          // console.log('触发了 sub 处理函数')
          this.count -= 1;
        },
      },
    });
  </script>
</body>
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

# 5.@指令

通过 v-on 绑定的事件处理函数,需要在 methods 节点中进行声明:

v-on: 简写是 @

<script>
  // 创建 Vue 的实例对象
  const vm = new Vue({
    // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
    el: "#app",
    // data 对象就是要渲染到页面上的数据
    data: {
      count: 0,
    },
    // methods 的作用,就是定义事件的处理函数
    methods: {
      add(n) {
        // 在 methods 处理函数中,this 就是 new 出来的 vm 实例对象
        // console.log(vm === this)
        console.log(vm);
        // vm.count += 1
        this.count += n;
      },
      sub() {
        // console.log('触发了 sub 处理函数')
        this.count -= 1;
      },
    },
  });
</script>
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

# 6.event 事件参数对象

在原生的 DOM 事件绑定中,可以在事件处理函数的形参处,接收事件参数对象 event。同理,在 v-on 指令

(简写为 @ )所绑定的事件处理函数中,同样可以接收到事件参数对象 event,示例代码如下:

<script>
  // 创建 Vue 的实例对象
  const vm = new Vue({
    // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
    el: "#app",
    // data 对象就是要渲染到页面上的数据
    data: {
      count: 0,
    },
    methods: {
      add(e, n) {
        this.count += n;
        console.log(e);

        // 判断 this.count 的值是否为偶数
        if (this.count % 2 === 0) {
          // 偶数
          e.target.style.backgroundColor = "red";
        } else {
          // 奇数
          e.target.style.backgroundColor = "";
        }
      },
    },
  });
</script>
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

绑定事件并且传参:

$event 的应用场景:如果默认的事件对象 e 被覆盖了,则可以手动传递一个 $event。例如:

<button @click="add(3, $event)"></button>

methods: {
   add(n, e) {
			// 如果在方法中要修改 data 中的数据,可以通过 this 访问到
			this.count += 1
   }
}
1
2
3
4
5
6
7
8

# 7.event 事件修饰符

在事件处理函数中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。因此,

vue 提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发进行控制。常用的 5 个事件修饰符如下:

image-20230701115422041

  • .prevent

    <a @click.prevent="xxx">链接</a>
    
    1
  • .stop

    <button @click.stop="xxx">按钮</button>
    
    1

# 8.@keyup 按键修饰符

在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符,例如:

<body>
  <!-- 希望 Vue 能够控制下面的这个 div,帮我们在把数据填充到 div 内部 -->
  <div id="app">
    <input type="text" @keyup.esc="clearInput" @keyup.enter="commitAjax" />
  </div>

  <!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
  <script src="./lib/vue-2.6.12.js"></script>
  <!-- 2. 创建 Vue 的实例对象 -->
  <script>
    // 创建 Vue 的实例对象
    const vm = new Vue({
      // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
      el: "#app",
      // data 对象就是要渲染到页面上的数据
      data: {},
      methods: {
        clearInput(e) {
          console.log("触发了 clearInput 方法");
          e.target.value = "";
        },
        commitAjax() {
          console.log("触发了 commitAjax 方法");
        },
      },
    });
  </script>
</body>
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

# 9.v-model 双向绑定指令

vue 提供了 v-model 双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据。

  1. input 输入框
    • type="radio"
    • type="checkbox"
    • type="xxxx"
  2. textarea
  3. select
<body>
  <!-- 希望 Vue 能够控制下面的这个 div,帮我们在把数据填充到 div 内部 -->
  <div id="app">
    <p>用户的名字是:{{ username }}</p>
    <input type="text" v-model="username" />
    <hr />
    <input type="text" :value="username" />
    <hr />
    <select v-model="city">
      <option value="">请选择城市</option>
      <option value="1">北京</option>
      <option value="2">上海</option>
      <option value="3">广州</option>
    </select>
  </div>

  <!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
  <script src="./lib/vue-2.6.12.js"></script>
  <!-- 2. 创建 Vue 的实例对象 -->
  <script>
    // 创建 Vue 的实例对象
    const vm = new Vue({
      // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
      el: "#app",
      // data 对象就是要渲染到页面上的数据
      data: {
        username: "zhangsan",
        city: "2",
      },
    });
  </script>
</body>
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

# 10.v-model 的修饰符

为了方便对用户输入的内容进行处理,vue 为 v-model 指令提供了 3 个修饰符,分别是:

image-20230701115729911

<!-- 希望 Vue 能够控制下面的这个 div,帮我们把数据填充到 div 内部 -->
<div id="app">
  <input type="text" v-model.number="n1" /> +
  <input type="text" v-model.number="n2" /> = <span>{{ n1 + n2 }}</span>
  <hr />
  <input type="text" v-model.trim="username" />
  <button @click="showName">获取用户名</button>
  <hr />
  <input type="text" v-model.lazy="username" />
</div>
1
2
3
4
5
6
7
8
9
10

# 11.v-show 条件渲染指令

条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:

  1. v-show 的原理是:动态为元素添加或移除 display: none 样式,来实现元素的显示和隐藏
    • 如果要频繁的切换元素的显示状态,用 v-show 性能会更好
  2. v-if 的原理是:每次动态创建或移除元素,实现元素的显示和隐藏
    • 如果刚进入页面的时候,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时 v-if 性能更好

在实际开发中,绝大多数情况,不用考虑性能问题,直接使用 v-if 就好了!!!

<p v-if="flag">这是被 v-if 控制的元素</p>
<p v-show="flag">这是被 v-show 控制的元素</p>
1
2

# 12.v-if 指令

v-if 指令在使用的时候,有两种方式:

  1. 直接给定一个布尔值 true 或 false

    <p v-if="true">被 v-if 控制的元素</p>
    
    1
  2. 给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏

    <p v-if="type === 'A'">良好</p>
    
    1

# 13.v-else 指令

v-if 可以单独使用,或配合 v-else 指令一起使用:

注意:v-else 指令必须配合 v-if 指令一起使用,否则它将不会被识别!

<div id="app">
  <p v-if="flag">这是被 v-if 控制的元素</p>
  <p v-show="flag">这是被 v-show 控制的元素</p>

  <hr />
  <div v-if="type === 'A'">优秀</div>
  <div v-else-if="type === 'B'">良好</div>
  <div v-else-if="type === 'C'">一般</div>
  <div v-else></div>
</div>
1
2
3
4
5
6
7
8
9
10

# 14.v-else-if 指令

v-else-if 指令,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:

注意:v-else-if 指令必须配合 v-if 指令一起使用,否则它将不会被识别!

<div id="app">
  <p v-if="flag">这是被 v-if 控制的元素</p>
  <p v-show="flag">这是被 v-show 控制的元素</p>

  <hr />
  <div v-if="type === 'A'">优秀</div>
  <div v-else-if="type === 'B'">良好</div>
  <div v-else-if="type === 'C'">一般</div>
  <div v-else></div>
</div>
1
2
3
4
5
6
7
8
9
10

# 15.v-for 列表渲染指令

vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。v-for 指令需要使

用 item in items 形式的特殊语法,其中:

  • items 是待循环的数组
  • item 是被循环的每一项

v-for 指令还支持一个可选的第二个参数,即当前项的索引。语法格式为 (item, index) in items,示例代码如下:

<body>
  <!-- 希望 Vue 能够控制下面的这个 div,帮我们把数据填充到 div 内部 -->
  <div id="app">
    <table class="table table-bordered table-hover table-striped">
      <thead>
        <th>索引</th>
        <th>Id</th>
        <th>姓名</th>
      </thead>
      <tbody>
        <!-- 官方建议:只要用到了 v-for 指令,那么一定要绑定一个 :key 属性 -->
        <!-- 而且,尽量把 id 作为 key 的值 -->
        <!-- 官方对 key 的值类型,是有要求的:字符串或数字类型 -->
        <!-- key 的值是千万不能重复的,否则会终端报错:Duplicate keys detected -->
        <tr v-for="(item, index) in list" :key="item.id">
          <td>{{ index }}</td>
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
        </tr>
      </tbody>
    </table>
  </div>

  <!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
  <script src="./lib/vue-2.6.12.js"></script>
  <!-- 2. 创建 Vue 的实例对象 -->
  <script>
    // 创建 Vue 的实例对象
    const vm = new Vue({
      // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
      el: "#app",
      // data 对象就是要渲染到页面上的数据
      data: {
        list: [
          { id: 1, name: "张三" },
          { id: 2, name: "李四" },
          { id: 3, name: "王五" },
          { id: 4, name: "张三" },
        ],
      },
    });
  </script>
</body>
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

# 16.v-for 列表 key 元素

使用 key 维护列表的状态

当列表的数据变化时,默认情况下,vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能。但这种

默认的性能优化策略,会导致有状态的列表无法被正确更新。

为了给 vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲

染的性能。此时,需要为每项提供一个唯一的 key 属性:

<tbody>
  <!-- 官方建议:只要用到了 v-for 指令,那么一定要绑定一个 :key 属性 -->
  <!-- 而且,尽量把 id 作为 key 的值 -->
  <!-- 官方对 key 的值类型,是有要求的:字符串或数字类型 -->
  <!-- key 的值是千万不能重复的,否则会终端报错:Duplicate keys detected -->
  <tr v-for="(item, index) in list" :key="item.id">
    <td>{{ index }}</td>
    <td>{{ item.id }}</td>
    <td>{{ item.name }}</td>
  </tr>
</tbody>
1
2
3
4
5
6
7
8
9
10
11

key 的注意事项

① key 的值只能是字符串或数字类型

② key 的值必须具有唯一性(即:key 的值不能重复)

③ 建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)

④ 使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)

⑤ 建议使用 v-for 指令时一定要指定 key 的值(既提升性能、又防止列表状态紊乱)

# 17.label 的 for 属性

通过 label 的 for 属性,可以控制 for 引用的元素

<body>
  <input type="checkbox" id="cb1" />
  <label for="cb1"></label>
  <hr />
  <input type="checkbox" id="cb2" />
  <label for="cb2"></label>
</body>
1
2
3
4
5
6
7

# 18.v-model 和 v-bind 的区别

v-modelv-bind 是 Vue.js 中的两个指令,用于处理数据绑定。它们之间的区别如下:

v-model 是一个双向数据绑定指令,用于在表单元素和 Vue 实例中的数据之间建立双向绑定关系。它可以用于处理输入、选择和表单等交互操作。当在表单元素上使用 v-model 时,表单元素的值会自动与 Vue 实例中的数据进行同步。当 Vue 实例中的数据改变时,表单元素的值也会相应地更新。例如:

<input type="text" v-model="message" />
1

在上面的代码中,message 是 Vue 实例中的一个数据属性,该输入框的值会自动与 message 的值保持同步。

v-bind 是一个单向数据绑定指令,用于将 Vue 实例中的数据绑定到 HTML 元素的属性或组件的属性上。它可以动态地将 Vue 实例中的数据绑定到 HTML 元素上的属性,从而实现数据的动态更新。例如:

<img v-bind:src="imageSrc" />
1

在上面的代码中,imageSrc 是 Vue 实例中的一个数据属性,通过 v-bind 指令将其绑定到 <img> 元素的 src 属性上。当 imageSrc 的值发生改变时,<img> 元素的 src 属性也会相应地更新。

需要注意的是,v-model 主要用于表单元素的双向绑定,而 v-bind 则用于一次性地将数据绑定到元素的属性上。

# 19.props 的作用与使用

Props(属性)是 Vue.js 中用于父组件向子组件传递数据的一种机制。通过 Props,可以在组件之间进行数据的传递和通信。子组件接收父组件传递的数据后,可以在自身进行处理或展示。

Props 的作用和使用如下:

  1. 数据传递:通过 Props,父组件可以将数据传递给子组件。父组件可以在组件标签上使用属性的形式将数据传递给子组件。子组件可以在 props 选项中声明接收的属性,然后在组件内部使用这些属性。例如:

父组件模板:

<template>
  <child-component :message="parentMessage"></child-component>
</template>
1
2
3

子组件代码:

Vue.component('child-component', {
  props: ['message'],
  template: '<div>{{ message }}</div>'
});
1
2
3
4

在上述代码中,parentMessage 是父组件中的数据,通过将其绑定到子组件的 message 属性上,子组件可以接收到该数据并在自身展示。

  1. 数据响应:父组件传递给子组件的 Props 数据是响应式的。这意味着如果父组件的数据发生改变,子组件会立即更新接收到的 Props 数据。
  2. 数据验证:Props 可以进行验证,以确保父组件传递的数据满足特定的要求。可以使用 Props 的验证选项来验证传递的数据的类型、必需性等。
Vue.component('child-component', {
  props: {
    message: {
      type: String,
      required: true
    }
  },
  template: '<div>{{ message }}</div>'
});
1
2
3
4
5
6
7
8
9

在上述代码中,message 属性必须为字符串类型,并且是必需的。如果父组件没有传递 message 属性或者传递的不是字符串类型,Vue 会发出警告。

通过使用 Props,可以实现组件之间的数据传递和通信,提高了组件的复用性和可维护性。

# 五.vue 过滤器

# 1.过滤器

过滤器(Filters)是 vue 为开发者提供的功能,常用于文本的格式化。过滤器可以用在两个地方:插值表达式

和 v-bind 属性绑定。

过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”进行调用,示例代码如下:

<!--在双花括号中通过“管道符"调用 capitalize 过滤器,对 message 的值进行格式化-->
<p>{{ message | capitalize }}</p>
<!--在 v-bind 中通过“管道符"调用 formatId 过滤器,对 rawId 的值进行格式化-->
<div v-bind:id="rawId | formatId"></div>
1
2
3
4

# 2.定义过滤器

<script>
  const vm = new Vue({
    el: "#app",
    data: {
      message: "hello vue.js",
      info: "title info",
    },
    //在filters 节点下定义"过滤器"
    filter: {
      capitalize(str) {
        //把首字母转为大写的过滤器
        return str.charAt(0).toUpperCase() + str.slice(1);
      },
    },
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在 filters 节点下定义的过滤器,称为“私有过滤器”,因为它只能在当前 vm 实例所控制的 el 区域内使用。

# 4.全局过滤器

如果希望在多个 vue 实例之间共享过滤器,则可以按照如下的格式定义全局过滤器:

<script>
  const vm = new Vue({
    el: "#app",
    data: {
      message: "hello vue.js",
      info: "title info",
    },
    //在filters 节点下定义"过滤器"
    filter: {
      capitalize(str) {
        //把首字母转为大写的过滤器
        return str.charAt(0).toUpperCase() + str.slice(1);
      },
    },
  });
  //全局过滤器-独立于每个vm实例之外
  //Vue.filter()方法接收两个参数:
  //第1个参数,是全局过滤器的"名字“
  //第2个参数,是全局过滤器的"处理函数“
  Vue.filter("capitalize", (str) => {
    return str.charAt(0).toUpperCase() + str.slice(1) + "~~";
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 5.连续多个过滤器

过滤器可以串联地进行调用,例如:

<!--把message的值,交给filterA 进行处理-->
<!--把filterA处理的结果,再交给filterB 进行处理-->
<!--最终把filterB处理的结果,作为最终的值渲染到页面上--> {{ message | filterA |
filterB }}
1
2
3
4

举例:

<p>{{text | capitalize | maxLength}}</p>
1
//全局过滤器-首字母大写 Vue.filter("capitalize", (str) => { return
str.charAt(0).toUpperCase() + str.slice(1) + "~~"; });
//全局过滤器-控制文本的最大长度 Vue.filter("maxLength", (str) => { if
(str.length <= 10) return str; return str.slice(0, 11) + "……"; });
1
2
3
4

# 6.过滤器传参

过滤器的本质是 JavaScript 函数,因此可以接收参数,格式如下:

<!-- arg1 和 arg2是传递给filterA的参数-->
<p>{{ message | filterA(arg1, arg2) }}</p>
//过滤器处理函数的形参列表中: //第一个参数:永远都是"管道符“前面待处理的值
//从第二个参数开始,才是调用过滤器时传递过来的arg1和 arg2参数
Vue.filter('filterA', (msg,arg1,arg2) =>{ //过滤器的代码逻辑... })
1
2
3
4
5
<p>{{ text | capitalize | maxLength(5) }}</p>
1
/全局过滤器-首字母大写 Vue.filter('capitalize', (str) => { return
str.charAt(0).toUpperCase() + str.slice(1) + '~~' })
//全局过滤器-控制文本的最大长度 Vue.filter('maxLength', (str, len = 10) => { if
(str.length <= len) return str return str.slice(0, len) + '...' })
1
2
3
4

# 7.兼容性

过滤器的兼容性

过滤器仅在 vue 2.x 和 1.x 中受支持,在 vue 3.x 的版本中剔除了过滤器相关的功能。

在企业级项目开发中:

  • 如果使用的是 2.x 版本的 vue,则依然可以使用过滤器相关的功能
  • 如果项目已经升级到了 3.x 版本的 vue,官方建议使用计算属性或方法代替被剔除的过滤器功能

具体的迁移指南,请参考 vue 3.x 的官方文档给出的说明:

https://v3.vuejs.org/guide/migration/filters.html#migration-strategy

# 8.时间格式化

假设你想要格式化的日期是 ${date},你可以使用 Day.js 库来格式化这个日期。首先,你需要将 Day.js 库添加到你的 HTML 文件中:

<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.6/dayjs.min.js"></script>
1

然后,在你的 JavaScript 文件中,你可以使用以下代码来格式化 ${date}

const formattedDate = dayjs(`${date}`).format('YYYY-MM-DD HH:mm:ss');
1

这将把 ${date} 格式化为年-月-日 时:分:秒 的格式。你可以将这个值赋给一个新的变量 formattedDate,然后在插值表达式中使用它:

`当前时间是:${formattedDate}`
1

这将把当前时间以年-月-日 时:分:秒 的格式插入到字符串中。

# 9.过滤器总结

过滤器的注意点:

  1. 要定义到 filters 节点下,本质是一个函数
  2. 在过滤器函数中,一定要有 return 值
  3. 在过滤器的形参中,可以获取到“管道符”前面待处理的那个值
  4. 如果全局过滤器和私有过滤器名字一致,此时按照“就近原则”,调用的是”私有过滤器“

# 六.品牌列表案例

# 1.文件目录

image-20230701122430298

# 2.品牌列表案例.html

<!DOCTYPE html>
<html lang="en">
  <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" />
    <title>品牌列表案例</title>
    <link rel="stylesheet" href="./lib/bootstrap.css" />
    <link rel="stylesheet" href="./css/brandlist.css" />
  </head>

  <body>
    <div id="app">
      <!-- 卡片区域 -->
      <div class="card">
        <div class="card-header">添加品牌</div>
        <div class="card-body">
          <!-- 添加品牌的表单区域 -->
          <!-- form 表单元素有 submit 事件 -->
          <form @submit.prevent="add">
            <div class="form-row align-items-center">
              <div class="col-auto">
                <div class="input-group mb-2">
                  <div class="input-group-prepend">
                    <div class="input-group-text">品牌名称</div>
                  </div>
                  <input
                    type="text"
                    class="form-control"
                    placeholder="请输入品牌名称"
                    v-model.trim="brand"
                  />
                </div>
              </div>
              <div class="col-auto">
                <button type="submit" class="btn btn-primary mb-2">添加</button>
              </div>
            </div>
          </form>
        </div>
      </div>

      <!-- 表格区域 -->
      <table class="table table-bordered table-hover table-striped">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">品牌名称</th>
            <th scope="col">状态</th>
            <th scope="col">创建时间</th>
            <th scope="col">操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="item in list" :key="item.id">
            <td>{{ item.id }}</td>
            <td>{{ item.name }}</td>
            <td>
              <div class="custom-control custom-switch">
                <!-- 使用 v-model 实现双向数据绑定 -->
                <input
                  type="checkbox"
                  class="custom-control-input"
                  :id="'cb' + item.id"
                  v-model="item.status"
                />
                <!-- 使用 v-if 结合 v-else 实现按需渲染 -->
                <label
                  class="custom-control-label"
                  :for="'cb' + item.id"
                  v-if="item.status"
                  >已启用</label
                >
                <label class="custom-control-label" :for="'cb' + item.id" v-else
                  >已禁用</label
                >
              </div>
            </td>
            <td>{{ item.time | dateFormat }}</td>
            <td>
              <a href="javascript:;" @click="remove(item.id)">删除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>

    <script src="./lib/dayjs.min.js"></script>
    <script src="./lib/vue-2.6.12.js"></script>
    <script>
      // 声明格式化时间的全局过滤器
      Vue.filter("dateFormat", function (time) {
        //1.对time进行格式化处理,得到YYYY-MM-DD HH:mm:ss
        //2.把格式化的结果,return 出去
        //直接调用dayjs()得到的是当前时间
        //dayjs(给定的日期时间)得到指定的日期
        return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
      });

      const vm = new Vue({
        el: "#app",
        data: {
          // 用户输入的品牌名称
          brand: "",
          // nextId 是下一个,可用的 id
          nextId: 4,
          // 品牌的列表数据
          list: [
            { id: 1, name: "宝马", status: true, time: new Date() },
            { id: 2, name: "奔驰", status: false, time: new Date() },
            { id: 3, name: "奥迪", status: true, time: new Date() },
          ],
        },
        methods: {
          // 点击链接,删除对应的品牌信息
          remove(id) {
            this.list = this.list.filter((item) => item.id !== id);
          },
          // 阻止表单的默认提交行为之后,触发 add 方法
          add() {
            // 如果判断到 brand 的值为空字符串,则 return 出去
            if (this.brand === "") return alert("必须填写品牌名称!");

            // 如果没有被 return 出去,应该执行添加的逻辑
            // 1. 先把要添加的品牌对象,整理出来
            const obj = {
              id: this.nextId,
              name: this.brand,
              status: true,
              time: new Date(),
            };
            // 2. 往 this.list 数组中 push 步骤 1 中得到的对象
            this.list.push(obj);
            // 3. 清空 this.brand;让 this.nextId 自增 +1
            this.brand = "";
            this.nextId++;
          },
        },
      });
    </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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

# 3.brandlist.css

body {
  padding: 15px;
  user-select: none;
}
1
2
3
4

# 4.dayjs

使用方式:dayjs()方法拼接 format()方法可以格式化指定的时间

<script>
    let time = new Date()
    //1、格式化年份
    console.log(dayjs(time).format('YYYY')) // 2023 (YYYY 四月份的年份,YY则是23)
    //2、格式化月份
    console.log(dayjs(time).format('MM')) // 01 (MM-两位数的月份)
    //3、格式化 年-月-日
    console.log(dayjs(time).format('YYYY-MM-DD')) // 2023-01-19
    console.log(dayjs(time).format('YYYY年MM月DD日')) // 2023年01月19日
    //4、格式化 年月日时分秒:YYYY-MM-DD HH:mm:ss
    console.log(dayjs(time).format('YYYY-MM-DD HH:mm:ss')) // 2023-01-19 16:25:23
</script>
1
2
3
4
5
6
7
8
9
10
11
12

image-20230712232037135

上次更新: 11/26/2024, 10:00:43 PM