一、Vue2 凭啥在前端圈火了这么多年?
前端圈里框架更新换代跟坐过山车似的,Vue2 都不是最新版本了,为啥还有不少团队抓着它用?新手想入门前端,选 Vue2 学合不合适?怎么高效把 Vue2 核心知识吃透?今天咱从优势、核心概念、实战步骤这些角度,把 Vue2 那点事儿唠明白~
Vue2 能火这么久,离不开几个“杀手锏”级的优势:
响应式系统,简单说,你在 data 里定义的变量,数据一变,页面能自动更新,完全不用手动操作 DOM,它靠 Object.defineProperty
实现“数据劫持”,把数据变成“牵一发而动全身”的状态,比如做待办清单,新增一条任务,列表自动渲染,省了一大堆 DOM 操作的代码,开发效率直接起飞~
然后是组件化开发,前端项目越做越大,把页面拆成一个个组件就很关键,像电商网站的商品卡片、导航栏,每个组件有自己的结构、样式、逻辑,复用的时候直接拿过来用,维护也清晰,团队协作时,你写导航组件,我写商品组件,互不干扰,效率拉满~
还有成熟的生态,围绕 Vue2 有一堆现成工具:路由用 vue-router
,状态管理用 vuex
,UI 库有 Element-UI、Ant Design Vue 这些,拿来就能用,新手想学,网上教程、社区问答一抓一大把,学习门槛低,自然火得久~
友好的学习曲线,和 React、Angular 比,Vue2 的语法更像“人话”,指令(v-bind
、v-model
)一看就懂,就算是没接触过前端的新手,花几天也能写个简单项目,这也是它圈粉无数的原因~
新手学 Vue2 得先搞懂哪些核心概念?
想玩转 Vue2,这几个核心概念必须吃透:
响应式数据
Vue2 里,data
函数返回的对象属性是“响应式”的——数据变了,页面自动更,但有个坑:如果给对象新增属性(this.obj.newProp = '新属性'
),页面不会更新,得用 Vue.set
或者 this.$set
才行(因为 Object.defineProperty
只能劫持已有的属性),举个例子:
data() { return { user: { name: '张三' } } }, methods: { addAge() { // 错误写法:直接新增属性,页面不更新 this.user.age = 18; // 正确写法:用 $set this.$set(this.user, 'age', 18); } }
组件通信
组件之间传数据是刚需,父传子用 props
,子组件接收后直接用;子传父靠 $emit
触发事件,父组件监听事件拿数据。
<!-- 父组件 --> <ChildComponent :title="parentTitle" @handleClick="parentMethod" /> <p><!-- 子组件 --> <script> export default { props: ['title'], // 接收父组件的 title methods: { clickHandler() { this.$emit('handleClick', '子组件传的值'); // 触发事件,传数据 } } } </script>
生命周期
Vue 实例从创建到销毁有一系列“阶段”,每个阶段能做不同的事:
created
:数据初始化完成,能发请求拿数据;mounted
:DOM 渲染完成,能操作 DOM 元素(比如初始化第三方插件);beforeDestroy
:实例销毁前,清理定时器、事件监听等,避免内存泄漏。
知道每个阶段干啥,写代码时才不会“乱了节奏”~
指令
Vue 的指令是“语法糖”,简化 DOM 操作,常用的有:
v-bind
:绑定属性(缩写 ),<img :src="imgUrl" />
;v-model
:双向绑定,比如输入框<input v-model="username" />
,数据和视图同步变;v-for
:循环渲染列表,记得加:key
(帮助 Vue 高效更新 DOM),<li v-for="(item, index) in list" :key="index">{{ item }}</li>
。
从环境搭建到写第一个 Vue 页面,步骤咋走?
想实操 Vue2,得先把开发环境和项目结构搞明白:
环境搭建
首先装 Node.js(Vue 项目依赖 npm 管理包),去 Node 官网下对应系统的版本,装完后打开命令行,输入 node -v
和 npm -v
,能看到版本号就说明装对了。
然后装 vue-cli(官方脚手架,快速生成项目):
npm install -g @vue/cli
装完后用 vue -V
(注意是大写 V)验证版本。
创建项目
用 vue-cli 创建 Vue2 项目:
vue create my-vue-project
命令行里选 Default ([Vue 2] babel, eslint) 模板,等待项目创建完成。
项目结构解析
进入项目目录 cd my-vue-project
,核心目录是 src
:
main.js
:项目入口,创建 Vue 实例,挂载到#app
节点;components
:放可复用的组件(HelloWorld.vue
);App.vue
:根组件,整合页面结构。
写第一个组件
在 components
下新建 MyComponent.vue
,写三段式代码:
<template> <div class="my-component"> {{ message }} </div> </template> <p><script> export default { data() { return { message: '我的第一个 Vue 组件~' } } } </script></p> <p><style scoped> .my-component { color: red; } </style>
然后在 App.vue
里引入并使用:
<template> <div id="app"> <MyComponent /> </div> </template> <p><script> import MyComponent from './components/MyComponent.vue' export default { components: { MyComponent // 注册组件 } } </script>
执行 npm run serve
启动开发服务器,浏览器打开 http://localhost:8080
,就能看到红色的“我的第一个 Vue 组件~”啦~
组件化开发在 Vue2 里咋落地?
组件化是 Vue2 开发的核心,得学会拆分、通信、复用:
组件拆分原则
按功能或业务模块拆,比如做博客页面,头部导航(Header.vue
)、文章列表(ArticleList.vue
)、侧边栏(Sidebar.vue
)各成组件,每个组件只负责自己的逻辑,解耦又好维护。
父子组件通信进阶
父传子用 props
,子传父用 $emit
,但还有些细节:
props
是单向数据流,子组件不能直接改父组件传的值,得通过$emit
让父组件自己改;- 如果父组件传的是对象/数组,子组件改了内部属性,父组件也会变(因为引用类型是浅劫持),这时候要注意数据污染,必要时深拷贝。
插槽(Slot)实现灵活布局
插槽让组件更灵活,比如做个布局组件 Layout.vue
,里面留插槽:
<template> <div class="layout"> <header><slot name="header">默认头部</slot></header> <main><slot>默认内容</slot></main> <footer><slot name="footer">默认底部</slot></footer> </div> </template>
使用时插入自定义内容:
<Layout> <template v-slot:header><h1>我的博客</h1></template> <p>这是文章内容...</p> <template v-slot:footer><p>版权信息</p></template> </Layout>
具名插槽(name
)指定位置,匿名插槽(没 name)放默认位置,灵活度拉满~
动态组件切换场景
做选项卡、标签页时,用 <component :is="currentComponent"></component>
切换组件。
<template> <div> <button @click="currentComponent = 'ComponentA'">显示A</button> <button @click="currentComponent = 'ComponentB'">显示B</button> <component :is="currentComponent"></component> </div> </template> <p><script> import ComponentA from './ComponentA.vue' import ComponentB from './ComponentB.vue' export default { components: { ComponentA, ComponentB }, data() { return { currentComponent: 'ComponentA' } } } </script>
不用写一堆 v-if / v-else
,代码简洁多了~
路由和状态管理,Vue2 项目里咋整合?
中大型项目离不开路由和状态管理,这俩工具得会用:
vue-router 实现单页路由
首先装 vue-router@3
(Vue2 对应 3.x 版本):
npm install vue-router@3
然后在 src
下新建 router/index.js
,配置路由:
import Vue from 'vue' import Router from 'vue-router' import Home from '@/views/Home.vue' import About from '@/views/About.vue' <p>Vue.use(Router)</p> <p>export default new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', // 路由懒加载:访问时再加载组件,减少首屏体积 component: () => import('@/views/About.vue') } ] })
在 main.js
里引入路由并挂载:
import router from './router' <p>new Vue({ router, // 挂载路由 render: h => h(App) }).$mount('#app')
页面中用 <router-view></router-view>
显示匹配的组件,用 <router-link to="/">首页</router-link>
做导航~
路由传参有两种方式:
- query:参数拼在 URL 上(如
/user?name=张三
),用this.$route.query.name
取值; - params:动态路由(如
path: '/user/:id'
),URL 是/user/123
,用this.$route.params.id
取值。
vuex 管理全局状态
装 vuex
:
npm install vuex
在 src
下新建 store/index.js
,配置核心模块:
import Vue from 'vue' import Vuex from 'vuex' <p>Vue.use(Vuex)</p> <p>export default new Vuex.Store({ state: { // 存全局数据 count: 0 }, mutations: { // 同步修改 state(必须同步,因为要追踪变化) increment(state) { state.count++ } }, actions: { // 异步操作(比如发请求),然后提交 mutation asyncIncrement({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }, getters: { // 处理 state 数据(类似计算属性) doubleCount(state) { return state.count * 2 } } })
在 main.js
里挂载 store:
import store from './store' <p>new Vue({ store, // 挂载状态管理 router, render: h => h(App) }).$mount('#app')
组件里用 this.$store.commit('increment')
触发 mutation,用 this.$store.dispatch('asyncIncrement')
触发 action,用 this.$store.state.count
取状态~
Vue2 项目部署和性能优化有哪些实用技巧?
项目开发完,得部署上线,还要优化性能:
项目部署
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。