近几天更新完毕,不定期持续更新,建议关注收藏点赞。
这里主要是了解vue2,会提到vue3与其对比,但不一定很全,想了解vue3的全部请访问另一个笔记。点击跳转
工具推荐
工欲善其事,必先利其器。
vscode插件
Vetur:vue代码高亮插件
 VueHelper:代码提示插件
vue-devtools
vue-devtools 是一个专门为 Vue.js 开发者打造的 浏览器开发者工具插件,可以用来 调试、查看和修改 Vue 应用的内部状态。
 简单来说,它就像给 Vue 应用装了个“透视眼”,让你能轻松看到组件之间是怎么工作的。
- vue-devtools 能干嘛?【5点】
查看组件结构:类似一棵树,展示你的应用是由哪些组件组成的,谁嵌套谁。你可以直接点进每个组件,看到它的名字、props、data、computed 等。
实时查看和修改数据:能看到组件当前的数据(data、props、computed)。修改数据还能立刻看到页面更新,适合调试。
事件追踪:查看哪个组件发出了哪个自定义事件($emit)。可以看到事件的名字、参数、传播链等。
Vuex 调试(如果你用了 Vuex):查看 Vuex 的 state、getters、mutations、actions。
时间旅行调试(Time Travel Debugging):可以前进后退查看状态变化。
性能检测(性能分析标签页):查看组件的更新频率、渲染开销,找出性能瓶颈。 - 安装
Chrome 插件商店搜索 vue-devtools 安装。或者在 Firefox 也可以装。
如果是开发桌面应用或在本地调试,Vue 官方还提供了独立版(Electron 应用)。 - 使用
确保你的 Vue 应用在开发模式Vue 在生产模式下默认关闭调试信息,vue-devtools 可能检测不到。所以开发时要确保没有 Vue.config.productionTip = false 或类似压缩优化设置。 
ESLint
它是一个代码检查工具,用于JavaScript 和 TypeScript 的静态代码分析工具,主要功能是识别并修复代码中的问题,比如语法错误、不一致的风格、潜在的 bug 等。
npm install eslint --save-dev
npx eslint --init #初始化配置
#这个命令会引导你选择项目的风格、使用的框架(React、Vue等)、
#是否使用 TypeScript 等,并生成一个配置文件(.eslintrc.js、.eslintrc.json 等)。
npx eslint yourfile.js #检查这个文件
npx eslint yourfile.js --fix #自动修复代码
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 
比如:如果在main.js 声明个变量而不使用,则终端和网页都会报错,因为不严谨。
- 解决方式
方式1: 手动解决掉错误, 以后项目中会讲如何自动解决
方式2: 暂时关闭eslint检查, 在vue.config.js中配置后重启服务 
module.exports={
	//其他配置略
	lintOnSave:false//关闭eslint检查
}
- 1
 - 2
 - 3
 - 4
 
- 常配合使用的插件/配置
eslint-config-airbnb: Airbnb 代码规范
eslint-plugin-react: 检查 React 项目
eslint-plugin-import: 管理模块导入
eslint-config-prettier: 配合 Prettier,关闭 ESLint 中和 Prettier 冲突的规则 
JSX语法扩展
JSX(JavaScript XML)是一种 JavaScript 的语法扩展,主要用于Vue/ React。它让你可以在 JavaScript 中写出类似 HTML 的代码,描述界面的结构。
 Vue 本身没有默认使用 JSX,默认用的是模板语法(.vue 文件里的 < template>),但支持 JSX 语法扩展,但JSX比Vue模版的性能差,因为没有模版同级别的编译时优化。
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Alice" />;
- 1
 - 2
 - 3
 - 4
 - 5
 
- JSX 的核心特点
 
- 像 HTML 但不是 HTML
 
const name = "ChatGPT";
const element = <h1>Hello, {name}!</h1>;
- 1
 - 2
 
- 标签必须闭合
 
// 正确
<img src="logo.png" />
- 1
 - 2
 
- 只能有一个根节点
 
// 错误 ❌
return (
  <h1>Title</h1>
  <p>Description</p>
);
// 正确 ✅
return (
  <div>
    <h1>Title</h1>
    <p>Description</p>
  </div>
);
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 
- class 改为 className
因为 class 是 JavaScript 的关键字,所以在 JSX 中写样式类时要用 className 
<div className="container">Hello</div>
- 1
 
- JSX 配合 ESLint
为了让 ESLint 正确识别 JSX,你需要使用对应的插件和解析器: 
#react
npm install eslint-plugin-react eslint-plugin-react-hooks --save-dev
#vue
npm install --save-dev eslint eslint-plugin-vue @vue/eslint-config-standard babel-eslint eslint-plugin-babel eslint-plugin-import eslint-plugin-node eslint-plugin-promise
#vue3还需要
npm install @vitejs/plugin-vue-jsx @vue/babel-plugin-jsx --save-dev
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
//配置 .eslintrc.js 示例
//react
module.exports = {
  parser: 'babel-eslint',
  extends: [
    'eslint:recommended',
    'plugin:react/recommended'
  ],
  plugins: ['react'],
  rules: {
    'react/prop-types': 'off'
  },
  settings: {
    react: {
      version: 'detect'
    }
  }
};
//vue
module.exports = {
  root: true,
  env: {
    node: true,
  },
  parserOptions: {
    parser: 'babel-eslint',
    ecmaVersion: 2020,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true, // 开启 JSX 支持
    },
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended', // Vue 3 推荐配置
    'plugin:import/recommended',
    'plugin:promise/recommended',
  ],
  plugins: ['vue', 'babel'],
  rules: {
    // 自定义规则,例如关闭 console 警告
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    // Vue 特有规则
    'vue/no-multiple-template-root': 'off', // Vue 3 不再强制单根节点
  },
};
//babel.config.js
module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  plugins: ['@vue/babel-plugin-jsx'],
};
//Vue 组件中使用 JSX
<script setup>
import { defineComponent } from 'vue';
export default defineComponent({
  setup() {
    return () => <div class="hello">Hello from JSX!</div>;
  },
});
</script>
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 
简介
vue的底层还是原生js。开发更加的效率和简洁, 易于维护, 现在很多项目都是用vue开发的。
 渐进式声明式组件化的javacript框架,官网地址: https://cn.vuejs.org/ 。
 渐进式: 逐渐进步, 想用什么就用什么, 不必全都使用
- vue的特点: 
  
- 渐进式
 - 声明式渲染:基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。
 - 数据驱动视图 (响应式):Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM。
 - 极少的去写DOM操作相关代码
 - 双向绑定
 - 组件系统
 - 不兼容IE8及以下浏览器(因为vue的响应式原理是基于es5的Object.defineProperty(),而这个方法不支持ie8及以下)
 
 - 库 v.s. 框架
库: 封装的属性或方法 (例jquery.js),还是那个规则、语法、元素。
框架: 拥有自己的规则和元素, 比库强大的多 (例vue.js) - 工程化开发方式:在webpack环境中开发vue,这是最推荐的企业常用方式
 - 目前Vue2已停止维护,之后所有Vue3的变化都用高亮显示
最简单的实例 
<div id="app">
  <button @click="count++">
    Count is: {{ count }}
  button>
div>
- 1
 - 2
 - 3
 - 4
 - 5
 
import { createApp, ref } from 'vue'
createApp({
  setup() {
    return {
      count: ref(0)
    }
  }
}).mount('#app')
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 
设计模式
- vue是MVVM设计模式
vue源码内采用MVVM设计模式思想, 大大减少了DOM操作, 提高开发效率
用数据驱动视图改变, 操作dom的事,由vue源码内部来做。vue是数据变化视图自动更新, 减少操作DOM时间, 提高开发效率 
- 在vue中,不推荐直接手动操作DOM!!!
 - 在vue中,通过数据驱动视图,不要在想着怎么操作DOM,而是想着如何操作数据!!(思想转变) 
  
- MVVM
MVVM,一种软件架构模式,决定了写代码的思想和层次
M: model数据模型 (data里定义)
V: view视图 (html页面)
VM: ViewModel视图模型 (vue.js源码)


MVVM通过数据双向绑定让数据自动地双向同步 不再需要操作DOM
V(修改视图) -> M(数据自动同步)
M(修改数据) -> V(视图自动同步) 
 - MVVM
 
M层和V层可以互相改变
在devtool工具可以改变M层的变量, 观察V层(视图的自动同步);(devtool工具就是chrome浏览器检查工具(开发者模式)里多出来的vue工具)
- 对比MVC设计模式 
  
- 组件化:模块独立,复用性强,适用于所有现代前端项目,如React, Vue
 - Flux/Redux:单向数据流,适合大型状态管理,见于react
 - MVC: 也是一种设计模式, 组织代码的结构, 是model数据模型, view视图, Controller控制器, 在控制器这层里编写js代码, 来控制数据和视图关联
应用于早期小项目 - MVVM: 即Model-View-ViewModel的简写。即模型-视图-视图模型, VM是这个设计模式的核心, 连接v和m的桥梁, 内部会监听DOM事件, 监听数据对象变化来影响对方. 我们称之为数据绑定
应用于Vue, Angular 等现代框架,响应式数据双向绑定 
 
React 并不严格是 MVVM,为什么很多人还是说 React 属于 MVVM?因为它也有:Model(state、props)、View(JSX)、某种“中间层逻辑”(用 Hook、useEffect 实现的)但这些功能都融合在组件中,不像 Vue 的 ViewModel 那么清晰分层。
React 是一种以组件为中心、函数式编程风格、支持单向数据流的前端库。它既不像传统 MVC,也不是典型 MVVM,而是一种组件驱动的 UI 架构。
React 的不同点:
- React 是单向数据流
 
数据从组件的 state/props 向下流动到 UI。
没有像 Vue 那样的“自动双向绑定”。- 没有“真正意义上的 ViewModel”
 
在 React 中,没有一个专门处理逻辑与数据绑定的“ViewModel”。
组件本身就承担了“视图”和“一部分逻辑”的职责。- React 强调函数式思想
 
使用 Hook 来组合逻辑,而不是 ViewModel。
倾向于将 UI 表现为“状态的纯函数”。
快速入门
- 单文件组件
使用一种类似 HTML 格式的文件来书写 Vue 组件,它被称为单文件组件 (也被称为 *.vue 文件,英文 Single-File Components,缩写为 SFC)。顾名思义,Vue 的单文件组件会将一个组件的逻辑 (JavaScript),模板 (HTML) 和样式 (CSS) 封装在同一个文件里。 
//app.vue
<script setup>
import { ref } from 'vue'
// “ref”是用来存储值的响应式数据源。
const count = ref(0)
</script>
<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>
<style scoped>
button {
  font-weight: bold;
}
</style>
//更复杂的例子
<!--
这个示例展示了如何通过 v-on 指令处理用户输入。
-->
<script setup>
import { ref } from 'vue'
const message = ref('Hello World!')
function reverseMessage() {
  // 通过其 .value 属性
  // 访问/修改一个 ref 的值。
  message.value = message.value.split('').reverse().join('')
}
function notify() {
  alert('navigation was prevented.')
}
</script>
<template>
  <!--
    注意我们不需要在模板中写 .value,
    因为在模板中 ref 会自动“解包”。
  -->
  <h1>{{ message }}</h1>
  <!--
    绑定到一个方法/函数。
    这个 @click 语法是 v-on:click 的简写。
  -->
  <button @click="reverseMessage">Reverse Message</button>
  <!-- 也可以写成一个内联表达式语句 -->
  <button @click="message += '!'">Append "!"</button>
  <!--
    Vue 也为一些像 e.preventDefault() 和 e.stopPropagation()
    这样的常见任务提供了修饰符。
  -->
  <a href="https://vuejs.org" @click.prevent="notify">
    A link with e.preventDefault()
  </a>
</template>
<style>
button, a {
  display: block;
  margin-bottom: 1em;
}
</style>
//attribute绑定
<!--
现在我们将元素的 attribute / property 响应式地绑定到状态上。
这个 :title 语法是 v-bind:title 的简写。
-->
<script setup>
import { ref } from 'vue'
const message = ref('Hello World!')
const isRed = ref(true)
const color = ref('green')
function toggleRed() {
  isRed.value = !isRed.value
}
function toggleColor() {
  color.value = color.value === 'green' ? 'blue' : 'green'
}
</script>
<template>
  <p>
    <span :title="message">
      Hover your mouse over me for a few seconds to see my dynamically bound title!
    </span>
  </p>
  <!--
  除了普通字符串之外,
  class 绑定还特别支持了对象和数组
  -->
  <p :class="{ red: isRed }" @click="toggleRed">
    This should be red... but click me to toggle it.
  </p>
  <!-- 样式绑定也支持对象和数组 -->
  <p :style="{ color }" @click="toggleColor">
    This should be green, and should toggle between green and blue on click.
  </p>
</template>
<style>
.red {
  color: red;
}
</style>
//条件&循环
<!--
我们可以通过 v-if 和 v-for 指令条件性地或循环地渲染内容。
-->
<script setup>
import { ref } from 'vue'
const show = ref(true)
const list = ref([1, 2, 3])
</script>
<template>
  <button @click="show = !show">Toggle List</button>
  <button @click="list.push(list.length + 1)">Push Number</button>
  <button @click="list.pop()">Pop Number</button>
  <button @click="list.reverse()">Reverse List</button>
  <ul v-if="show && list.length">
    <li v-for="item of list">{{ item }}</li>
  </ul>
  <p v-else-if="list.length">List is not empty, but hidden.</p>
  <p v-else>List is empty.</p>
</template>
//表单绑定
<!--
我们可以使用 v-model 指令在状态和表单输入之间创建双向绑定。
-->
<script setup>
import { ref } from 'vue'
const text = ref('Edit me')
const checked = ref(true)
const checkedNames = ref(['Jack'])
const picked = ref('One')
const selected = ref('A')
const multiSelected = ref(['A'])
</script>
<template>
  <h2>Text Input</h2>
  <input v-model="text">
  <p>{{ text }}</p>
  <h2>Checkbox</h2>
  <input type="checkbox" id="checkbox" v-model="checked">
  <label for="checkbox">Checked: {{ checked }}</label>
  <!--
    多个复选框可以绑定到
    相同的 v-model 数组
  -->
  <h2>Multi Checkbox</h2>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <p>Checked names: {{ checkedNames }}</p>
  <h2>Radio</h2>
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <p>Picked: {{ picked }}</p>
  <h2>Select</h2>
  <select v-model="selected">
    <option disabled value="">Please select one</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <p>Selected: {{ selected }}</p>
  <h2>Multi Select</h2>
  <select v-model="multiSelected" multiple style="width:100px">
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <p>Selected: {{ multiSelected }}</p>
</template>
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 - 70
 - 71
 - 72
 - 73
 - 74
 - 75
 - 76
 - 77
 - 78
 - 79
 - 80
 - 81
 - 82
 - 83
 - 84
 - 85
 - 86
 - 87
 - 88
 - 89
 - 90
 - 91
 - 92
 - 93
 - 94
 - 95
 - 96
 - 97
 - 98
 - 99
 - 100
 - 101
 - 102
 - 103
 - 104
 - 105
 - 106
 - 107
 - 108
 - 109
 - 110
 - 111
 - 112
 - 113
 - 114
 - 115
 - 116
 - 117
 - 118
 - 119
 - 120
 - 121
 - 122
 - 123
 - 124
 - 125
 - 126
 - 127
 - 128
 - 129
 - 130
 - 131
 - 132
 - 133
 - 134
 - 135
 - 136
 - 137
 - 138
 - 139
 - 140
 - 141
 - 142
 - 143
 - 144
 - 145
 - 146
 - 147
 - 148
 - 149
 - 150
 - 151
 - 152
 - 153
 - 154
 - 155
 - 156
 - 157
 - 158
 - 159
 - 160
 - 161
 - 162
 - 163
 - 164
 - 165
 - 166
 - 167
 - 168
 - 169
 - 170
 - 171
 - 172
 - 173
 - 174
 - 175
 - 176
 - 177
 - 178
 - 179
 - 180
 - 181
 - 182
 - 183
 - 184
 - 185
 - 186
 - 187
 - 188
 - 189
 - 190
 - 191
 - 192
 - 193
 - 194
 - 195
 - 196
 - 197
 - 198
 - 199
 - 200
 - 201
 - 202
 - 203
 - 204
 - 205
 - 206
 - 207
 
- vue组件风格:两种不同的风格书写:选项式 API 和组合式 API。
在生产项目中:当你不需要使用构建工具,或者打算主要在低复杂度的场景中使用 Vue,例如渐进增强的应用场景,推荐采用选项式 API。
当你打算用 Vue 构建完整的单页应用,推荐采用组合式 API + 单文件组件。 
- 组合式 API (Composition API)
通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与搭配使用。这个 setup attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如,