《学Vue这几年,我踩过的坑和攒下的野路子》
你可能刚学完HTML、CSS、JavaScript然后听别人说“现在都流行用框架了Vue简单你学一下”。然后你去网上找教程看了一堆还是有点懵什么叫组件化什么叫数据驱动为什么我用原生JS写得好好的非要学个框架我当时也是这么过来的。这篇文章我假设你只会HTML、CSS、JS基础从零开始带你搞明白Vue到底是什么、怎么用、为什么这么用。每一步都拆开讲代码每一行都有注释。别怕跟着敲就完了。一、先别急着写代码搞明白Vue到底是个啥你用原生JS写页面时步骤大概是这样的先在HTML里写好结构用document.getElementById之类的找到那个元素监听事件改它的内容或样式一个小功能还行页面一复杂代码就乱成一团。你需要手动维护“数据”和“页面显示”之间的关系数据变了你得自己更新DOM。Vue干了一件什么事呢它帮你自动同步数据和页面。数据变了页面自动更新页面输入了东西数据自动修改。你不用再手动操作DOM了。这就叫数据驱动视图也叫响应式。二、搭建环境不用装一堆东西先在线体验很多教程一上来就让你装Node.js、装Vue CLI、配Webpack。0基础直接劝退。我先教你一个零配置的办法直接在浏览器里跑Vue。打开任何一个HTML文件在head里加一行html!-- 这行引入Vue的核心库直接从CDN加载不用下载任何东西 -- script srchttps://unpkg.com/vue3/dist/vue.global.js/script然后就能用了。是的就这么简单不需要npm不需要构建工具。三、第一个Vue程序让数据出现在页面上先来个最简单的例子感受一下什么叫“数据变了页面也变”。html !DOCTYPE html html head title第一个Vue程序/title !-- 第一步引入Vue库 -- script srchttps://unpkg.com/vue3/dist/vue.global.js/script /head body !-- 第二步定义一个区域告诉Vue要管理这个区域 -- div idapp !-- 两个大括号是Vue的插值语法里面写变量名会自动显示变量的值 -- h1{{ message }}/h1 p你点击了 {{ count }} 次/p !-- click 是Vue的事件绑定等于原生JS的 onclick -- button clickaddCount点我加1/button /div script // 第三步创建一个Vue应用 const { createApp } Vue // 从Vue全局对象里解构出createApp方法 // createApp接收一个配置对象返回一个应用实例 const app createApp({ // data是一个函数返回一个对象对象里的属性就是“响应式数据” data() { return { message: 你好Vue, // 页面里{{ message }}会显示这个 count: 0 // {{ count }}会显示这个 } }, // methods里放方法页面里可以调用 methods: { addCount() { this.count // this指向当前Vue实例this.count就是data里的count // 不用管页面count变了{{ count }}自动更新 } } }) // 把应用挂载到idapp的div上Vue开始管理这个div及其内部的所有内容 app.mount(#app) /script /body /html来一行一行拆解发生了什么引入Vue那行script标签加载了Vue的核心代码浏览器就有了Vue这个全局对象。div idapp这是Vue的“地盘”Vue只会管理这个div里面的东西。{{ message }}双花括号叫“插值”把data里message的值显示在这里。message变了这里自动变。clickaddCount是v-on:的简写绑定点击事件。点按钮就调用methods里的addCount方法。data(){}data必须是一个函数返回一个对象。对象里的所有属性都会被Vue变成响应式的改它们页面就自动变。this.count在methods里用this.xxx访问data里的xxx。Vue自动帮你绑定了this。app.mount(#app)把Vue实例和页面上的div挂上钩这一行执行之后Vue才开始工作。把这段代码复制到一个.html文件里双击打开点按钮试试。是不是点一下数字就变这就是Vue最基本的魔力。四、Vue的几个核心概念用人话解释1. 插值语法{{ }}双花括号里可以写变量名也可以写简单的表达式htmldiv idapp !-- 直接显示变量 -- p{{ name }}/p !-- 可以写简单的JS表达式 -- p{{ age 1 }}/p !-- 可以调用字符串方法 -- p{{ name.toUpperCase() }}/p !-- 三元运算也行 -- p{{ isVip ? 尊贵会员 : 普通用户 }}/p /div但是不能写语句比如{{ if(true){...} }}不行。复杂的逻辑放到computed或methods里。2. 指令Vue提供的特殊属性指令就是写在HTML标签上、以v-开头的特殊属性。它们告诉Vue这个标签有特殊行为。v-bind动态绑定属性htmldiv idapp !-- v-bind:属性名变量可以简写成 :属性名变量 -- !-- 下面两种写法完全一样 -- img v-bind:srcimgUrl / img :srcimgUrl / !-- 原生写法是写死srcVue里让src跟数据联动 -- a :hreflinkUrl点我跳转/a !-- class也可以动态绑 -- div :classboxClass我的样式由数据决定/div /div script const { createApp } Vue createApp({ data() { return { imgUrl: https://example.com/photo.jpg, // 图片地址存数据里 linkUrl: https://www.baidu.com, // 链接地址存数据里 boxClass: red-box // 类名存数据里 } } }).mount(#app) /scriptv-if / v-show条件显示htmldiv idapp !-- v-if条件为false时元素直接从DOM里移除 -- p v-ifisLogin欢迎回来{{ username }}/p !-- v-else配合v-if使用前面的条件不成立就显示这个 -- p v-else请先登录/p !-- v-show条件为false时只是加了个display:none元素还在DOM里 -- p v-showhasNewMsg你有新消息/p /divv-if和v-show的区别记住一句话频繁切换用v-show条件很少改变用v-if。v-for列表渲染htmldiv idapp ul !-- v-for会遍历数组每次循环生成一个li -- !-- :key是必须的给每个元素一个唯一标识Vue用它来高效更新 -- li v-foritem in fruitList :keyitem.id {{ item.name }} —— 单价{{ item.price }}元 /li /ul /div script const { createApp } Vue createApp({ data() { return { fruitList: [ { id: 1, name: 苹果, price: 5 }, { id: 2, name: 香蕉, price: 3 }, { id: 3, name: 橘子, price: 4 } ] } } }).mount(#app) /scriptv-model双向绑定这是Vue最爽的功能之一htmldiv idapp !-- v-model把input的value和data里的变量双向绑定 -- !-- 你在输入框里打字data里的值自动变data里的值变了输入框里也自动变 -- input v-modelinputText placeholder随便打点字 / p你输入的是{{ inputText }}/p /div script const { createApp } Vue createApp({ data() { return { inputText: // 初始为空 } } }).mount(#app) /script有了v-model你就不用写document.getElementById然后手动监听input事件了。这个功能在表单里非常常用。五、计算属性 computed当数据需要算一算的时候data里存的是原始数据但有时候你要展示的是“算出来”的结果。比如价格要加单位、名字要拼接后缀。htmldiv idapp p原价{{ price }} 元/p !-- computed里的属性用法跟data一样直接{{ }} -- p折后价{{ discountPrice }} 元/p /div script const { createApp } Vue createApp({ data() { return { price: 100 // 原始价格 } }, // computed里定义计算属性 computed: { discountPrice() { // 自动依赖priceprice变了discountPrice会自动重新算 return this.price * 0.8 } } }).mount(#app) /scriptcomputed和methods有什么区别methods每次调用都重新执行。computed有缓存只有它依赖的数据变了才会重新计算性能更好。所以展示用computed事件处理用methods这样区分。六、组件Vue的灵魂学到这你已经能用Vue写出一个页面了。但真正做项目页面不可能全写在一个HTML文件里不然代码会几千行找都找不到。Vue允许你把页面拆成一个个小组件每个组件管自己那一小块。就像搭乐高大城堡是一块块小积木拼起来的。用CDN方式创建组件稍微复杂点我先用最简化的方式让你理解htmldiv idapp !-- 用组件就像用HTML标签一样 -- MyCard title第一个卡片 content这是卡片内容/MyCard MyCard title第二个卡片 content另一张卡片/MyCard /div script const { createApp } Vue // 定义一个组件 const MyCard { // props组件接收外部传进来的数据 props: [title, content], // template组件的HTML结构 template: div styleborder:1px solid #ccc; padding:10px; margin:10px; h3{{ title }}/h3 p{{ content }}/p /div } const app createApp({ data() { return {} } }) // 注册组件之后就能在#app里用了 app.component(MyCard, MyCard) app.mount(#app) /script用人话解释组件传值父组件#app用titlexxx把数据传给子组件MyCard子组件用props: [title, content]声明“我要接收这两个值”子组件里用{{ title }}直接使用这就是父子组件通信最基本的模式。七、实际项目里我们会用单文件组件(.vue文件)上面的写法只适合学习和小demo。真正的项目一个组件就是一个.vue文件长这样vue!-- MyButton.vue -- !-- 一个.vue文件分三块template结构、script逻辑、style样式 -- template !-- 这就是组件的HTML -- button clickhandleClick :classbtnClass {{ btnText }} /button /template script setup // setup是Vue3的组合式API写法比data/methods更灵活 import { ref } from vue // ref用来创建响应式数据 // 定义props接收父组件传来的数据 const props defineProps({ btnText: { type: String, // 类型是字符串 default: 点我 // 不传就默认显示点我 }, btnType: { type: String, default: primary } }) // 定义事件告诉父组件“我被点了” const emit defineEmits([btn-click]) // 计算class名 const btnClass btn- props.btnType // 点击处理函数 function handleClick() { // emit触发事件父组件用btn-click监听 emit(btn-click, 按钮被点了这是传过去的数据) } /script style scoped /* scoped意思是这里的样式只对这个组件生效不会影响别的组件 */ button { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; } .btn-primary { background: #1890ff; color: white; } .btn-danger { background: #ff4d4f; color: white; } /style父组件用的时候vuetemplate div !-- 传btnText和btnType给子组件 -- !-- btn-click监听子组件发出的btn-click事件 -- MyButton btnText删除 btnTypedanger btn-clickhandleDelete / /div /template script setup import MyButton from ./MyButton.vue // 引入组件 function handleDelete(msg) { console.log(msg) // 打印按钮被点了这是传过去的数据 } /script到这里你已经知道了.vue文件长什么样组件怎么传值父传子用props子传父用emit怎么引入和使用组件有了这些你就可以搭积木一样拼出一个完整的页面了。八、从零到能写项目的学习路线如果你看到这里有点晕没关系我给你列一个学习顺序跟着走就行第一天用CDN方式写几个小demo搞懂{{ }}、v-bind、v-model、v-if、v-for这些基础指令。就在单个HTML文件里写别碰构建工具。第二天学习computed和watch搞懂什么时候用哪个。第三天了解组件概念用CDN方式写几个小组件体会一下“拆积木”的感觉。第四天装Node.js然后用npm create vuelatest创建第一个Vue项目。这时候你会接触到Vite、单文件组件、ES模块导入。第五天在创建的项目里把之前用CDN写的demo用单文件组件的方式重写一遍。之后学习Vue Router页面路由、Pinia状态管理、Axios发送请求这时候你就能做一个完整的单页应用了。别急着一天全学完消化一个再学下一个。你学的是编程不是背课文代码多敲几遍自然就记住了。写在最后Vue说白了就是帮你干两件事自动更新页面和组件化开发。刚开始学指令记不住很正常不用死记硬背。多写几个页面常用的那几个自然就长在手指头上了。有什么问题评论区直接问。刚学的时候都会遇到各种奇怪的报错我也是一路踩坑踩过来的看到就会回你。加油Vue没你想的那么难。