# 一、Vue.js 简介

# 1、基本概述

官方描述:

Vue (opens new window) (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。

知识点:

vue 指令、vue 组件、路由、Vuex、vue 组件库等等

API 文档:

关于 vue 指令的更多信息可以查看 API 文档 (opens new window)

# 2、重要特性

  vue 中一个显著的特性就是 —— 数据驱动视图(数据劫持)

vue 会监听数据源的变化,从而自动重新渲染页面的结构。并且为单向的数据绑定。

  除此之外,在 vue 中还可以做到 —— 双向数据绑定(model)

图解
  • Data Bindings:vm 可以将数据的变量,响应式的反应到 View 层
  • DOM Listeners:vm 可以将 DOM 的监听绑定到 Model 层

在页面表单数据值发生变化时,双向数据绑定可以在不操作 DOM 的前提下,自动把 form 数据同步到数据源中。

# 3、MVVM 模型

  虽然 vue 没有完全遵循 MVVM 模型 (opens new window),但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。

说明

MVVM 架构将我们从 命令式编程 转移到了 声明式编程

思考:MVC 和 MVVM 的区别

  MVVM 相较于 MVC,它并没有 Controller,而是使用 ViewModel(Vue)进行数据和页面的相互绑定/交互

  举一个简单的例子:

MVVM 解释 位置
M 模型(Model) 对应 data 中的数据
V 视图(View) 模板
VM 视图模型(ViewModel) Vue 实例对象
<body>
  <!-- 视图(View) -->
  <div id="app">
    <span>{{ username }}</span>
  </div>

  <script>
    // 视图模型(ViewModel)
    const vm = new Vue({
      el: '#app',
      // 模型(Model)
      data: {
        username: 'zhangsan'
      }
    })
  </script>
</body>

# 二、template 渲染

 这部分内容是对后续 vue 学习中的一些技术难点做的一些知识铺垫 😂:

# 1、虚拟 DOM

  虚拟 DOM 由多个 VNode 组成,每个 VNode 代表了真实 DOM 中的一个节点,

  下面我们用官网的一张图看看 template 、渲染函数(Render Function)、虚拟 DOM、真实 DOM 的关系

# 2、VNode 产生

  关于Render Function (opens new window) 的作用,,我们可以看看下面的模拟代码:

Render Function 是用于创建 VNode 的一个函数

提示

  通过对比新旧 VNode,Vue 实现了高效的 DOM 更新(局部更新)机制

  其产生的性能优化点,可以体现在 v-for 中 key 属性的使用等方便

// Virtual DOM Tree
// VNode 的本质是一个 JavaScript 对象
const vnode = {
  type: 'div',
  props: {
    class: 'title',
    style: {
      'font-size': '30px',
      color: 'red'
    }
  },
  children: ['你好呀!'] // 树
}
<div class="title" style="font-size: 30px;color:red;">你好呀!</div>

# 3、渲染函数 h 🎈

  上面我们已经了解到了什么是虚拟 DOM,并且已经大致知道了 vue 底层使用了 渲染函数(Render Function)将 Template 模板转换为了 虚拟 DOM。

查看源码,我们可以发现 vue 中的渲染函数(Render Function)就是 h( ) 函数(也可以使用 createVNode( )函数)

提示

  基于 vue-cli 创建的 vue 项目,就使用了 render: (h) => h(App)来确定根组件。

  • vue 自动调用 h 函数
<script>
import Home from './Home.vue'

export default {
  components: {
    Home
  },
  data() {
    return {
      msg: '渲染函数h'
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}
</script>

<template>
  <div class="app">
    <p>你好呀!</p>
    <p>{{ msg }}</p>
    <button @click="increment">+1</button>
    <Home />
  </div>
</template>
  • 个人手动调用 h 函数
vue3 中的 h 函数
<script>
import { h, ref } from 'vue'
import Home from './Home.vue'

export default {
  setup() {
    const msg = ref('渲染函数h')
    const count = ref(1)

    const increment = () => {
      count.value++
    }

    const render = () => {
      return h('div', { className: 'app' }, [
        //
        h('p', null, '你好呀!'),
        h('p', null, `${msg.value}`),
        h('button', { onClick: increment }, '+1'),
        h(Home)
      ])
    }
  }
}
</script>

<template>
  <render />
</template>

在 react 中,我们可以直接编写 jsx,其最终同样会转换为 render 函数

<script>
import { h } from 'vue'
import Home from './Home.vue'

export default {
  data() {
    return {
      msg: '渲染函数h',
      count: 1
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },

  // render选项
  render() {
    return h('div', { className: 'app' }, [
      //
      h('p', null, '你好呀!'),
      h('p', null, `${this.msg}`),
      h('button', { onClick: this.increment }, '+1'),
      h(Home)
    ])
  }
}
</script>

# 4、使用 jsx

template vue-loader 库 npm install vue-loader -D
render 不需要转换
jsx bable 库 npm install @vue/babel-plugin-jsx -D

  当然在 vue 中使用 jsx 需要一些 npm 包和一些额外的配置才能使用:

jsx-vue2 (opens new window)

jsx-vue3 (opens new window)

<script lang="jsx">
import { h } from 'vue'
import Home from './Home.vue'

export default {
  data() {
    return {
      msg: '渲染函数h',
      count: 1
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },

  // render选项
  render() {
    return (
      <div class="app">
        <p>你好呀!</p>
        <p>{this.msg}</p>
        <button onClick={this.increment}>+1</button>
        <Home />
      </div>
    )
  }
}
</script>

# 5、界面渲染流程

  底层交给 vue 就可以了

template 模板(v-for/v-if 等)
  --通过 Render 函数编译解析为(通过数据劫持 Object.defineProperty、Proxy进行响应式更新数据)-->
虚拟 DOMs 树( h('div', { }, children))
  --将根据 diff 算法计算新旧 DOM 树差异更新到 -->
真实的 DOM 上

与 react 的区别

  数据如何更新交给开发者

直接返回 render()
  --并通过 Render 函数编译解析为(手动 this.setState 触发 render()更新)-->
虚拟 DOMs 树( React.createElement('div', { }, children))
  --将根据 diff 算法计算新旧 DOM 树差异更新到 -->
真实的 DOM 上

更新于 : 8/7/2024, 2:16:31 PM