前端发展史-原生JS到VUE3

284 阅读5分钟

刀耕火种的年代:早期前端开发思想

在Web发展的初期,前端开发者主要依赖于浏览器提供的底层API,如DOM编程和事件机制来构建网页。这种方式直接且直观,但随着网站复杂度的增加,频繁访问和修改DOM带来了性能上的挑战。浏览器内部,V8引擎(用于执行JavaScript代码)与渲染引擎(处理HTML和CSS)独立运作,类似两条并行的高速路,这导致了当JavaScript需要与DOM交互时,效率较低。

1. 跨系统通信成本

  • 当JavaScript代码需要修改DOM或查询其状态时,实际上是在两个独立运作的系统之间传递信息。这就好比两辆原本在不同高速公路上行驶的车突然需要交换乘客或货物一样,必须减速甚至停下才能安全完成交换。这种跨系统的通信带来了额外的时间开销。

2. 重排和重绘触发

  • 每次JavaScript修改了DOM结构或样式属性,渲染引擎都需要重新计算受影响元素的位置和尺寸(即重排),有时还需要重新绘制整个页面的一部分或全部(即重绘)。这些操作都是相当耗时的,尤其是在复杂的网页上。

3. JavaScript单线程限制

  • JavaScript是单线程运行的,这意味着在同一时间只能有一个任务被执行。如果一个JavaScript函数正在执行并且需要等待DOM更新完成才能继续,那么整个进程就会暂停,直到DOM更新完毕。这种阻塞现象会影响用户交互体验,特别是在频繁操作DOM的情况下。

jQuery时代:简化DOM操作

随着JavaScript代码量的增长,开发者们开始寻求更高效的方法来管理DOM操作。jQuery作为一款流行的JavaScript库,它通过提供简洁的API封装,极大地简化了DOM操作和其他常见的任务,比如AJAX请求。jQuery的出现标志着前端开发进入了一个更加便捷、高效的阶段。

<script>
$('#inp').val('你好')
</script>

现代前端框架:Vue与React引领潮流

进入现代前端框架时代,Vue和React等框架的诞生彻底改变了前端开发模式。这些框架强调数据驱动视图更新的理念,将开发者从繁琐的DOM操作中解放出来,使得他们能够更加专注于业务逻辑的实现。也就是我们写页面时只需要关注数据,而不需要分心操作那些繁琐的DOM

我以开发者需要使用的角度带大家领略一下vue的api

**{{}}**数据绑定

首先,我们开发者需要的是投入式的写页面,我们只在乎数据,因此,出现了 {{}} 进行数据绑定。

  <div id="app">
    <h2>{{title}}</h2>
  </div>
    <script>
  const App = {
    data() {
      return {
        title: 'todos'  
      }
    }
v-bind

我们不仅需要数值的绑定,可能还需要属性的绑定,例如,我们要绑定一张图片。

可能大家这时候想,我一样通过{{}}进行绑定就是了:

<div id="app">
    <img src={{imageSrc}}>
  </div>

image.png 结果并没有如预期一般绑定上去,{{}}表达式被当成了一个字符串,这时候,我们通过v-bind进行属性绑定

  <div id="app">
<img v-bind:src="image"></img>
  </div>
v-model

当我们想实现一个表单项,表单内的值跟h1标签内的值一样时,我们使用v-bind就显得有些余力不足了,因为他仅仅能监听数据的变化,但是不能去修改数据,为了做到数据的一致性,我们引入v-model

image.png
   <div id="app">
   <h1>{{title}}</h1>
  <input type="text" v-model="title">
</div>
computed

假如我们要渲染一个todolist,在一个地方显示列表完成项和未完成项。我们来试一试

        <span>{{todos.filter(item=>item.done===false).length}} / {{todos.length}}</span>
    </div>
  </div>
  <script>
  const App = {
    data() {
      return {
        title: 'todos',
        todos: [
          {title: '吃饭', done: false},
          {title: '睡觉', done: true},
        ],
      }
    }

有没有发现这样子在{{}}显得有些臃肿了呢?有点不符合我们数据驱动页面的写法了,那我们能不能把数据放在return里面进行返回呢?

data() {
      return {
        title: 'todos',
        todos: [
          {title: '吃饭', done: false},
          {title: '睡觉', done: true},
        ],
        todosLen:this.todos.length
      }
    }

结果报错了, 问题出在 todosLen 的定义上。您尝试在 data 函数中使用 this.todos.length 来初始化 todosLen,但在 data 函数中,this 关键字还没有指向 Vue 实例,因此 this.todos 是未定义的。

于是我们可以通过computed方法来返回计算属性

    computed: {
        all(){
            return this.todos.length
        },
        active(){
            return this.todos.filter(item=>item.done===false).length
        }
    }

假如同时还想做一些set操作,同时可以在computed属性中完成

// get set 两个都做 计算属性
   computed: {
        allDone:{
            get() {
                // this -> 计算属性
                return this.active === 0
             },
            set(val){
                this.todos.forEach(item=>item.done=val)
            }
        }
   }

从Vue 2.0到Vue 3.0的进化

Vue 2.0引入了组件化的概念,使开发者可以通过定义datamethodscomputed等选项来构建可复用的UI组件。然而,随着应用规模的增长,这种基于选项的API设计在大型项目中显得不够灵活。Vue 3.0则进一步推进了这一理念,推出了组合式API(Composition API),即setup函数,它允许开发者以一种更直观的方式组织逻辑,特别是对于那些超过一定复杂度的组件来说,组合式API提供了更好的代码维护性和复用性。 例如我有多个任务,不必将多个任务的数据放在一起,能更分类化的管理数据。

image.png