从前端原始社会到Vue.js新时代:来加入VUE的光荣进化吧⚡⚡⚡

1,717 阅读9分钟

Vue.js 的哲学从原始到现代:前端开发的进化之旅

在前端开发的历史长河中,我们经历了的原始社会到现代化的框架开发时代。Vue.js 正是这个进化过程中的一个关键角色,它不仅改变了开发者与DOM交互的方式,还引入了组件化和响应式的数据绑定,使得前端开发变得更加高效和愉悦。

原始社会:手动DOM操作的时代

早期的前端开发类似于“刀耕火种”,直接通过JavaScript底层API进行DOM操作和事件处理。这种方式虽然直接,但随着应用复杂度的增加,代码变得难以维护,频繁地访问和修改DOM导致性能问题频出。那时,浏览器的渲染引擎和V8 JavaScript引擎独立工作,为了优化用户体验,开发者需要小心翼翼地管理二者之间的互动。

案例:

该案例使用了纯JavaScript来监听输入框的变化,并将输入的内容显示在页面上的<h2>标签中。虽然实现了输入后在上方展示的功能,但是手动DOM有许多的缺点。

PixPin_2024-12-29_22-21-06.gif

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2 id="app"></h2>
    <input type="text" id="todo-input">
   
   <script>
    var app = document.getElementById('app');
    var todoInput = document.getElementById('todo-input');

   // change keyup keydown
    todoInput.addEventListener('input',function(event){
        var val= event.target.value //别的方法
        console.log(val,todoInput.value,this.value);
         app.innerHTML = val;
    })
    </script>
</body>
</html>

主要缺点:

  • 频繁的DOM访问:每次更新UI时都需要重新访问DOM,这可能导致性能瓶颈,特别是在需要频繁更新或大量DOM节点的情况下。
  • 代码冗长且复杂:随着应用功能的增加,直接操作DOM的代码会变得越来越冗长和复杂,难以理解和维护。

封建时期的变革:jQuery时代的局限与突破

随着jQuery等库的出现,前端开发进入了所谓的“封建时期”。jQuery简化了跨浏览器的兼容性问题,并提供了简洁的API来操作DOM,极大地提高了开发效率。尽管如此,当Web应用程序越来越复杂时,仅仅依靠jQuery这样的库已经不足以应对日益增长的需求。

与上面案例相同:

我们来了解一下jQuery就好,具体代码就不分析了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery Todo Input Example</title>
    <!-- 引入 jQuery -->
    <script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
    <h2 id="app"></h2>
    <input type="text" id="todo-input" placeholder="Enter text here">

    <script>
        $(document).ready(function() {
            // 初始化时设置输入框的值(可选)
            $('#todo-input').val('');  // 清空输入框或设置默认值

            // 监听输入框的变化
            $('#todo-input').on('input', function() {
                var val = $(this).val();  // 获取输入框的当前值
                console.log(val);         // 打印到控制台以供调试
                $('#app').html(val);      // 更新<h2>标签的内容为输入框的值
            });
        });
    </script>
</body>
</html>

jQuery相对于纯DOM操作的优点

  • 更简洁的语法:jQuery提供了简洁易读的方法来选择和操作DOM元素,减少了冗长的原生JavaScript代码。

jQuery相对于Vue.js的缺点

简单罗列一些重要的,

  1. 性能瓶颈

    • 频繁的DOM操作:每次更新UI都需要重新访问DOM,容易造成性能问题,特别是在需要频繁更新或大量DOM节点的情况下。
    • 无虚拟DOM优化:不像Vue那样具备虚拟DOM机制,不能智能地最小化实际DOM操作,影响渲染效率。
  2. 组件化能力不足

    • 模块化差:难以实现真正的组件化开发,不利于构建可复用的UI组件。

    • 缺乏单文件组件:Vue的单文件组件(SFC)允许在一个文件中定义模板、样式和脚本,极大地方便了代码组织和维护。

这就是为什么jQuery没有用到现在的原因,对于纯DOM,确实更优秀了,但是没有根本解决性能上的问题,

进化飞跃:Vue.js引领的开发新纪元

进入现代前端开发阶段,Vue.js成为了一股革新力量。它让开发者能够专注于业务逻辑而不是底层DOM操作,通过声明式的视图层,使数据和界面保持同步。Vue的核心思想在于其响应式系统——每当数据发生变化时,相关的视图部分会自动更新,而不需要手动干预DOM。这不仅提升了开发效率,还改善了用户体验,代表着前端开发的一次巨大进化。

质变之处:

而VUE相比于之前,对于频繁的DOM操作,Vue.js 通过其内部的响应式系统和虚拟DOM机制,实现了高效的批量收集DOM更新,减少了不必要的DOM操作。这种优化不仅提升了应用的性能,还简化了开发者的代码编写和维护工作。

简单图解: 减少了很多不必要的操作,优化了性能 image.png

选项式API(Options API)组合式API(Composition API)

让我们一起探索Vue的魅力,感受它带来的开发体验提升。下面是一个简单的待办事项(todos)应用示例,展示了Vue如何简化任务管理:

选项式API:todos案例:

图示:简单展示功能

PixPin_2024-12-29_22-47-43.gif

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>todos</title>
  <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.2.31/vue.global.min.js"></script>
  <style>
  .done {
    color: gray;
    text-decoration: line-through;
  }
  </style>
</head>
<body>
  <!-- 挂载点,vue 作用范围 -->
  <div id="app">
    <h2>{{title}}</h2>
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <ul>
      <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.done">
        <span :class="{done:todo.done}">{{todo.title}}</span>
      </li>
    </ul>
    <div>
      全选<input type="checkbox" v-model="allDone">
      <span>{{active}} / {{all}}</span>
    </div>
  </div>
  <script>
  const App = {
    data() {
      return {
        title: 'todos',
        todos: [
          {title: '吃饭', done: false},
          {title: '睡觉', done: true},
        ]
      }
    },
    methods: {
      addTodo() {
        this.todos.push({title: this.title, done: false})
        this.title = ''
      }
    },
    computed: {
      all() {
        return this.todos.length
      },
      active() {
        return this.todos.filter(todo => !todo.done).length
      },
      // get set 两个都做 
      allDone:{
       get(){
        // this -> 计算属性 计算属性改变 后面也会变
        return this.active ===0
       },
       set(val){
        //  数据和界面保持一致
        this.todos.forEach(todo=>{
          todo.done = val
        })    
       }
      }
    }
  }
  Vue.createApp(App).mount('#app')
  </script>
</body>
</html>

分析:

Script 标签:引入 Vue 3 的全局脚本
  • 定义 App 组件:使用 data() 定义组件的状态,包括 title 和 todos 数组。

  • 定义方法

    • addTodo():将当前 title 添加到 todos 数组,并清空 title
  • 定义计算属性

    • all:返回 todos 数组的长度。

    • active:返回未完成任务的数量。

    • allDone:这是一个带有 getter 和 setter 的计算属性,用于处理全选逻辑。

      • get():如果所有任务都已完成,则返回 true,否则返回 false
      • set(val):接受一个布尔值参数,并将所有任务的 done 属性设置为这个值。
  • 创建和挂载应用Vue.createApp(App).mount('#app') 创建一个新的 Vue 应用实例,并将其挂载到具有 ID app 的 DOM 元素上。

模板部分
  • <h2>{{title}}</h2>:显示标题,与 title 响应式变量绑定。

  • <input type="text" v-model="title" @keydown.enter="addTodo" />:文本输入框,通过 v-model 双向绑定到 title,并监听回车键调用 addTodo 方法。

  • <ul> 和 <li v-for="todo in todos">:无序列表,遍历 todos 数组生成每个任务项。

  • <input type="checkbox" v-model="todo.done">:复选框,与每个任务的 done 状态绑定。

  • <span :class="{done: todo.done}">{{todo.title}}</span>:根据任务完成状态动态应用 .done 类。

  • <div> 包含全选复选框和计数器,显示未完成和总任务数量。

缺点

可能在这个案例中没有太多体现选项式API的缺点,但是我们通过一张来自极客时间的图,我们就能很明显的发现:

image.png 结果:

  • 选项式API分了data、 methods、 computed三块区域,风格的优点是直观易懂,每个选项都有明确的用途。缺点是当组件变得复杂时,代码可能会分散且难以维护。你想想当你操作大型项目时,你改好了data中的数据,你要去找methods中是否有问题,中间隔开了几百行代码,是不是很繁琐。

那么就要引入组合式API

组合式API

  • 模块化: 相关的数据和方法被封装在一个函数中,使得代码更加模块化。
  • 复用性: 可以更容易地复用这些组合函数,提高代码的复用性。
  • 可测试性: 每个组合函数可以独立测试,提高了代码的可测试性。

案例:

    <script>
        const { ref, computed } = Vue;

        let App = {
            setup() {
                // title 相关模块
                let title = ref('todos');
                
                // todos 相关模块
                let todos = ref([
                    { title: '吃饭', done: false },
                    { title: '睡觉', done: true },
                ]);

                // 添加任务的方法
                function addTodo() {
                    if (title.value.trim()) {
                        todos.value.push({ title: title.value, done: false });
                        title.value = '';
                    }
                }

                // 计算属性
                const all = computed(() => todos.value.length);
                const active = computed(() => todos.value.filter(todo => !todo.done).length);

                // 全选/全不选功能
                const allDone = computed({
                    get: () => active.value === 0,
                    set: (value) => {
                        todos.value.forEach(todo => todo.done = value);
                    }
                });

                return {
                    title,
                    todos,
                    addTodo,
                    all,
                    active,
                    allDone
                };
            }
        };

        Vue.createApp(App).mount('#App'); // 注意这里的选择器与HTML中的id匹配
    </script>
</body>
</html>

总结: 组合式API允许我们将相关的逻辑封装在一起,形成所谓的“组合函数”(composables)。通过这种方式,所有与特定功能有关的状态、计算属性和方法都可以被集中管理。这种逻辑关注点分离的方法使得代码更加紧凑,减少了跨区域跳跃的需求,提高了开发效率。

计算属性是什么?

在选项式API中的computed就存放着计算属性,

概念:

在 Vue.js 中,计算属性(Computed Properties)是一种特殊的属性类型,它允许你声明性地定义一个属性,这个属性的值是基于其他数据属性的值动态计算出来的。计算属性的主要用途是在模板中简化复杂的逻辑表达式,并且它们具有缓存机制,只有在其依赖的数据发生变化时才会重新计算。

案例讲解:

我们使用选项式API中的例子进行分析其中的计算属性: allDone (带 getter 和 setter)

allDone: {
  get() {
    return this.active === 0
  },
  set(val) {
    this.todos.forEach(todo => {
      todo.done = val
    })
  }
}
  • 功能

    • getter:检查是否有未完成的任务(即 active 是否等于 0)。如果有未完成的任务,则返回 false;否则返回 true。这决定了全选复选框的状态。
    • setter:允许设置全选复选框的状态。当用户点击全选复选框时,它将遍历 todos 数组,并将每个任务的 done 属性设置为与复选框相同的状态(val)。
  • 依赖:getter 部分依赖于 active 计算属性,而 setter 则直接操作 todos 数据。

  • 用途:实现了全选/取消全选的功能,同时确保了数据和界面的一致性。

计算属性的特点

  1. 依赖响应式数据:计算属性会自动追踪其函数内部使用的响应式数据(如 data 或者 props),当这些数据发生变化时,计算属性会重新求值。
  2. 缓存机制:计算属性的结果会被缓存,除非它的相关依赖发生改变。这意味着如果计算属性所依赖的数据没有变化,那么即使多次访问该计算属性,也不会重复执行计算过程,从而提高了性能。
  3. 简洁的模板:通过将复杂的逻辑从模板中移出并放入计算属性中,可以使模板保持简单和易读。
  4. 可链式调用:计算属性可以相互依赖,即一个计算属性可以依赖另一个计算属性,形成链式调用关系。
  5. getter 和 setter:默认情况下,计算属性只提供 getter 方法来获取值。但也可以定义 setter 方法,允许我们对计算属性赋值时触发特定的行为。

迎接未来,共同进化

Vue.js不仅仅是另一个前端框架,它是对过去多年前端开发实践的一种总结和提升。它使得开发者可以更专注于构建应用本身,而不必纠结于复杂的DOM操作和状态管理。现在是时候加入Vue的光荣进化,开启属于你的现代化前端之旅了!🚀✨