class 1: vue初识

vue是由Evan You开源的轻量级前端框架,诞生于2014年,Vue.js 3采用MVVM架构,支持声明式编程、组件化开发、前端路由、单向数据流和数据双向绑定,同时提供了非常多的内置指令来简化对页面的操作。得益于这些特性,Vue.js很快就在前端圈火起来了。2016年10月,Evan You发布了Vue.js 3版本,新增了setup语法、CompositionAPI、TypeScript等特性

  • Vue.js是一套用于构建用户页面的渐进式框架,也就是可以在项目中一点点引入和使用Vue.js,而不需要用Vue.js来开发整个项目

特点

  1. 数据双向绑定:采用声明式编程,可以通过更改数据自动触发视图更新,与React类似
  2. 指令:Vue.js提供了许多内置指令,方便快速操作页面
  3. 组件化:支持组件化开发和封装可复用的代码,与ReactAngular类似
  4. 前端路由:支持前端路由、构建单页面应用(SPA)、服务器端渲染(SSR)应用,与ReactAngular类似
  5. 单向数据流:组件状态管理采用了单向数据流、与React类似

Vue.js 2和Vue.js 3优缺点对比

Vue.js 2缺点

  1. 对TypeScript支持不友好,对大型项目构建不利
  2. Mixin混入缺陷,Vue.js 2使用Mixin混入来抽取相同代码逻辑,但当一个组件有多个Mixin时,代码会变得难以阅读,因为不知道某个属性来自哪个Mixin,并且多个Mixin中的属性容易发生冲突
  3. 响应式系统缺陷,Vue.js 2采用Object.definedProperty来进行数据劫持,这种方式存在一些缺陷,比如无法劫持和监听对象添加或删除属性时的变化,无法遍历对象的每个属性,包括对于对象属性的对象需要进行深度遍历,导致性能低下
  4. 逻辑零散,Vue.js 2使用Options API编写组件,当实现某个功能时,对应的代码逻辑会被拆分到各个属性中,一旦组件变得复杂,逻辑就会变得零散

为了克服上述Vue.js 2存在的缺点,2020年9月Evan You发布了Vue.js 3,改版本带来了非常多新的变化

Vue.js 3优点

  1. monorepo源码管理。mono → \rightarrow 单个,repository → \rightarrow 仓库。monorepo的意思就是将许多项目的代码存储在同一个repository中。具体做法是将不同的模块拆分到packages目录下的子目录中,每个模块都可以看作一个独立的项目,具有自己的类型定义、API、测试用例等
  2. 采用TypeScript进行重构。Vue.js 2整个项目使用Flow进行类型检测,Flow在很多复杂场景中对类型的支持不是非常友好。从Vue.js 3开始,项目全面采用TypeScript进行重构。在TypeScript的加持下,Vue.js 3可以编写更加健壮的代码,同时更容易开发大型项目
  3. 采用Proxy进行数据劫持,这种方式会存在一些缺陷,比如当给对象添加或者删除属性时,是无法进行劫持和监听的;而Vue.js 3采用Proxy实现数据劫持。当给对象添加或者删除属性时,Proxy可以劫持和监听到,因为Proxy劫持的是整个对象,而且Proxy能劫持的类型比Object.definedProperty更丰富,不仅可以劫持set、get方法,还支持劫持in、delete操作等
  4. 编译阶段的优化,使得Vue.js 3在性能和效率方面有较大的提升。包括生成Block Tree、slot编译优化、diff算法优化等。具体可参考相关资料
  5. Composition API。Vue.js 2使用Options API来编写组件,其中包含data、props、methods、computed和生命周期等选项。在实现某个功能时,对应的代码逻辑会被拆分到各个属性中,一旦组件变得更大或更复杂,逻辑就会变的非常分散,需要在多个选项之间寻找,这不利于后期的维护和扩展;相比之下,Vue.js 3主要采用Composition API来编写组件,同时兼容Options API。Composition API包含ref、reactive、computed、watchEffect、watch等函数,Composition API可以将相关的代码放在同一处进行处理,封装成一个Hook函数来支持数据的响应式,并避免Mixins混入带来的缺陷。这样可以更加方便的实现在多个组件之间共享逻辑,也能够提高代码的可读性和可维护性
  6. 移除了一些非必要API,Vue.js 3移除了Vue实例中的$on$off$once API,还移除了一些特性,比如filter和内联模版等

架构

根据官方说法,Vue的整个设计受到MVVM架构的启发

  • MVVVM架构模式是一种软件体系结构,代表Model、View和ViewModel,如下图所示
    在这里插入图片描述
  • View代表视图层,用于编写页面布局
  • ViewModel负责把Model层的数据绑定到View层,将View层产生的DOM事件绑定到Model层
  • Model是模型层,用于提供模型和数据

createApp的对象参数

  • Vue实例是通过Vue.createApp函数创建的,该函数需要接收一个对象作为参数,该对象可以添加template、data、methods等属性

template属性

  • Vue.js 3中的template属性用于定义需要渲染的模板内容,其中包括HTML标签或组件,并最终将其挂载到<div id="app"></div>元素上,相当于为innerHTML赋值。在模板中,也会使用一些语法,例如{{}}@click
  • 在template属性中,使用字符串的方式来编写HTML页面,vs code并没有提供智能提示,这会降低编码效率和体验。为了解决这个问题,Vue.js 3提供了两种方式来优化模板的编写。
  1. 使用<script>标签,将其类型标记为x-template,并为其添加id属性。
  2. 使用任意标签(通常是<template>标签,因为它不会被浏览器渲染),并为其添加id属性

<template>标签或元素是一种用于保存客户端内容的机制。当页面加载时,该内容不会呈现,但可以在运行时使用javascript进行实例化
innerText:获取或设置元素的文本内容,不包含 HTML 标签。
textContent:获取或设置元素的文本内容,包括所有子节点。
outerHTML:获取或设置元素及其所有子元素的 HTML 内容。
innerHTML:获取或设置元素的 HTML 内容,但不包括元素本身。

  • 接下来让我们尝试使用不同方法,实现一个简单计数器。如果用原生javascript方式实现,代码可能是下面这样的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h2 class="counter"></h2>
    <button class="increment">+1</button>
    <button class="decrement">-1</button>
    <script>
        const counterE1 = document.querySelector(".counter")
        const increment = document.querySelector(".increment")
        const decrement = document.querySelector(".decrement")
        let counter = 100;
        counterE1.innerHTML = counter;
        // 监听按钮点击事件
        increment.addEventListener("click", () => {
            counter += 1;
            // 点击按钮后进行变量赋值
            counterE1.innerHTML = counter;
        })
        decrement.addEventListener("click", () => {
            counter -= 1;
            counterE1.innerHTML = counter;
        })
    </script>
</body>
</html>
  • 如果用vue.js 3实现,代码可能是下面这样的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <h2> {{ counter }}</h2>
        <button @click="increment"> +1 </button>
        <button @click="decrement"> -1 </button>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    counter: 100
                }
            },
            methods: {
                increment() {
                    this.counter += 1;
                },
                decrement() {
                    this.counter -= 1;
                }
            }
        })
        app.mount("#app")
    </script>
</body>
</html>
  • <script>标签的写法如下。这需要引入Vue.js 3源码。可以通过CDN或者本地引入,链接为https://unpkg.com/vue@3.4.38/dist/vue.global.js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    // 添加type="x-template"和id="here"两个属性
    <script type="x-template" id="here">
        <div>
            <h2> {{ message }}</h2>
            <h2> {{ counter }}</h2>
            <button @click="increment"> +1 </button>
            <button @click="decrement"> -1 </button>
        </div>
    </script>
    <script src="./js/vue.js"></script>
    <script>
        const app = Vue.createApp({
            template: '#here', // 通过id选择器选中页面上的模板,底层执行document.querySelector("#here")查找
            data() {
                return {
                    message: 'script',
                    counter: 100
                }
            },
            methods: {
                increment() {
                    this.counter += 1;
                },
                decrement() {
                    this.counter -= 1;
                }
            }
        })
        app.mount("#app")
    </script>
</body>
</html>
  • 使用<template>标签的写法可能是这样的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="here">
        <div>
            <h2> {{ message }}</h2>
            <h2> {{ counter }}</h2>
            <button @click="increment"> +1 </button>
            <button @click="decrement"> -1 </button>
        </div>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        Vue.createApp({
            template: "#here",
            data() {
                return {
                    message: 'template',
                    counter: 100,
                }
            },
            methods: {
                increment() {
                    this.counter += 1
                },
                decrement() {
                    this.counter -= 1
                }
            }
        }).mount('#app')
    </script>
</body>
</html>

data属性

  • 可以看到,上面的Vue.createApp的参数里面有一个data属性,它会用于为Vue.js组件定义响应式数据,该属性需要传入一个函数,该函数需要返回一个对象。该对象会被Vue.js响应式系统劫持,之后对该对象的修改或访问都会在劫持中被处理,所以该对象中定义的数据都是响应式的。比如在template中通过使用{{counter}},可访问到该对象中、定义的counter;当修改counter时,template中的{{counter}}也会发生改变

methods属性

  • methods属性需要传入一个对象,通常在这个对象中会定义很多方法。这些方法会绑定到模板中,例如上面反复定义的incrementdecremnet方法。在方法中,可以使用this关键字直接访问data返回对象的属性
  • methods属性中定义的方法不能使用箭头函数。否则无法使用this直接访问data中的数据,因为this在箭头函数中会在自己的上层作用域中查找this
  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值