# 一、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 包和一些额外的配置才能使用:
<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 上