Vue学习是一个渐进的过程,本文从基础知识入门开始,介绍了Vue的特点和优势,安装与环境搭建,并通过实例展示了Vue的数据绑定、组件化开发、事件处理与生命周期等核心概念。
Vue.js 是一个渐进式JavaScript框架,它允许开发者逐步地将应用功能添加到现有项目中。Vue的设计思想是尽可能地保持灵活性,同时提供强大的工具和库来帮助开发者构建动态的Web应用。Vue的核心库专注于视图层,体积小,易于学习,适合构建复杂前端应用。
Vue具有以下特点和优势:
Vue可以通过Node包管理器(如npm)或直接通过CDN引入。以下是通过npm安装Vue的步骤:
1 | npm install -g @vue/cli |
1 2 3 | vue create my-project cd my-project npm run serve |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!DOCTYPE html> < html > < head > < meta charset = "UTF-8" > < title >Vue Example</ title > <!-- 引入Vue --> < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://cdn.jsdelivr.net/npm/vue@2" ></ script > </ head > < body > < div id = "app" >{{ message }}</ div > < script > var app = new Vue({ el: '#app', data: { message: 'Hello, Vue!' } }); </ script > </ body > </ html > |
在HTML文件中,我们可以通过引入Vue并创建一个新的Vue实例来生成一个简单的应用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <!DOCTYPE html> < html > < head > < meta charset = "UTF-8" > < title >第一个Vue应用实例</ title > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://cdn.jsdelivr.net/npm/vue@2" ></ script > </ head > < body > < div id = "app" > < p >{{ message }}</ p > < p >{{ count }}</ p > </ div > < script > var app = new Vue({ el: '#app', data: { message: 'Hello, Vue!', count: 0 } }); </ script > </ body > </ html > |
上面的代码中,{{ message }}
和{{ count }}
是模板语法,Vue会自动将它们替换为对应的值。
Vue组件是可重用的Vue实例,具有独立的视图(HTML模板)、逻辑(JavaScript)和样式(CSS)。通过将应用分解为组件,可以提高代码的可维护性和复用性。
组件可以通过Vue构造器创建,然后通过<component>
标签来使用。下面是一个简单的组件例子:
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 | <!-- 组件模板 --> < script type = "x-template" id = "my-component-template" > < div > < h1 >{{ title }}</ hutorial > < p >{{ message }}</ p > </ div > </ script > < script > // 创建组件 Vue.component('my-component', { template: '#my-component-template', data: function() { return { title: 'Hello, Component!', message: 'This is a Vue component.' } } }); </ script > <!-- 使用组件 --> < div id = "app" > < my-component ></ my-component > </ div > < script > var app = new Vue({ el: '#app' }); </ script > |
组件之间可以通过Props传递数据,而通过Events来触发动作。下面是一个简单的例子,父组件传递数据给子组件,并通过事件触发动作。
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 | <!-- 子组件模板 --> < script type = "x-template" id = "child-template" > < div > < p >{{ message }}</ p > < button v-on:click = "sendMessageToParent" >Send Message</ button > </ div > </ script > < script > // 创建子组件 Vue.component('child-component', { template: '#child-template', props: ['message'], methods: { sendMessageToParent: function() { this.$emit('send-message', 'Hello from child!'); } } }); </ script > <!-- 父组件 --> < div id = "app" > < child-component v-bind:message = "'Hello from parent'" v-on:send-message = "handleMessage" ></ child-component > </ div > < script > // 父组件 var app = new Vue({ el: '#app', methods: { handleMessage: function(message) { console.log(message); } } }); </ script > |
Vue使用{{ }}
语法进行数据绑定,它可以绑定点数据、计算属性和方法。下面是一个简单的数据绑定示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | < div id = "app" > < p >{{ message }}</ p > < p >{{ count }}</ p > </ div > < script > var app = new Vue({ el: '#app', data: { message: 'Hello, Vue!', count: 0 }, methods: { increaseCount: function() { this.count++; } } }); </ script > |
v-model
指令用于处理表单元素的双向绑定。下面是一个简单的用法示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | < div id = "app" > < p >{{ message }}</ p > < input v-model = "message" /> </ div > < script > var app = new Vue({ el: '#app', data: { message: 'Hello, Vue!' } }); </ script > |
Vue提供了丰富的指令来帮助开发者处理常见的DOM操作。下面是一些常用指令的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | < div id = "app" > < p v-if = "condition" >显示条件为true</ p > < ul > < li v-for = "item in items" >{{ item }}</ li > </ ul > < button v-on:click = "handleClick" >点击我</ button > < a v-bind:href = "link" >链接</ a > </ div > < script > var app = new Vue({ el: '#app', data: { condition: true, items: ['apple', 'banana', 'cherry'], link: 'https://www.example.com' }, methods: { handleClick: function() { console.log('按钮被点击了'); } } }); </ script > |
Vue提供了事件绑定的语法,可以绑定各种事件,例如点击、鼠标移入等。下面是一个简单的事件绑定示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | < div id = "app" > < button v-on:click = "handleClick" >点击我</ button > </ div > < script > var app = new Vue({ el: '#app', methods: { handleClick: function() { console.log('按钮被点击了'); } } }); </ script > |
Vue提供了多个生命周期钩子,用于不同阶段的执行逻辑。生命周期钩子包括beforeCreate
、created
、beforeMount
、mounted
等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | < div id = "app" > < p >{{ message }}</ p > </ div > < script > Vue.component('my-component', { template: '< div >{{ message }}</ div >', data: function() { return { message: 'Hello, Component!' } }, created: function() { console.log('组件创建完成'); }, mounted: function() { console.log('组件挂载到DOM'); } }); var app = new Vue({ el: '#app' }); </ script > |
生命周期钩子的使用可以进行数据初始化、DOM操作等。例如,在mounted
钩子中,可以执行DOM操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | < div id = "app" > < p >{{ message }}</ p > </ div > < script > Vue.component('my-component', { template: '< div >{{ message }}</ div >', data: function() { return { message: 'Hello, Component!' } }, mounted: function() { console.log('组件挂载到DOM'); // 执行DOM操作 var element = this.$el.querySelector('p'); element.style.color = 'red'; } }); var app = new Vue({ el: '#app' }); </ script > |
Vue Router是Vue官方的路由插件,可以实现单页面应用的路由功能。以下是一个简单的Vue Router使用示例:
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 | <!DOCTYPE html> < html > < head > < meta charset = "UTF-8" > < title >Vue Router基础</ title > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://cdn.jsdelivr.net/npm/vue@2" ></ script > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://unpkg.com/vue-router/dist/vue-router.js" ></ script > </ head > < body > < div id = "app" > < router-link to = "/" >Home</ router-link > < router-link to = "/about" >About</ router-link > < router-view ></ router-view > </ div > < script > const Home = { template: '< div >Home Page</ div >' }; const About = { template: '< div >About Page</ div >' }; const router = new VueRouter({ routes: [ { path: '/', component: Home }, { path: '/about', component: About } ] }); new Vue({ el: '#app', router }); </ script > </ body > </ html > |
Vue Router支持路由动态参数,可以方便地传递参数。编程式导航可以通过router.push
、router.replace
等方法实现。
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 | <!DOCTYPE html> < html > < head > < meta charset = "UTF-8" > < title >路由动态参数与编程式导航</ title > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://cdn.jsdelivr.net/npm/vue@2" ></ script > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://unpkg.com/vue-router/dist/vue-router.js" ></ script > </ head > < body > < div id = "app" > < router-link to = "/" >Home</ router-link > < router-link to = "/about" >About</ router-link > < router-link :to = "{ name: 'user', params: { id: 123 }}" >User 123</ router-link > < button v-on:click = "navigateToUser" >导航到User</ button > < router-view ></ router-view > </ div > < script > const Home = { template: '< div >Home Page</ div >' }; const About = { template: '< div >About Page</ div >' }; const User = { template: '< div >User {{ $route.params.id }}</ div >' }; const router = new VueRouter({ routes: [ { path: '/', component: Home }, { path: '/about', component: About }, { path: '/user/:id', component: User, name: 'user' } ] }); var app = new Vue({ el: '#app', router, methods: { navigateToUser: function() { this.$router.push({ name: 'user', params: { id: 456 } }); } } }); </ script > </ body > </ html > |
Vuex是Vue官方的状态管理库,适用于复杂的应用状态管理。以下是一个简单的Vuex使用示例:
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 | <!DOCTYPE html> < html > < head > < meta charset = "UTF-8" > < title >Vuex状态管理简介</ title > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://cdn.jsdelivr.net/npm/vue@2" ></ script > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://unpkg.com/vuex@3" ></ script > </ head > < body > < div id = "app" > < p >{{ count }}</ p > < button v-on:click = "increment" >Increment</ button > </ div > < script > const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++; } } }); var app = new Vue({ el: '#app', store, computed: { count: function() { return this.$store.state.count; } }, methods: { increment: function() { this.$store.commit('increment'); } } }); </ script > </ body > </ html > |
待办事项应用是一个典型的前端应用,用户可以添加、删除和标记待办事项。应用的主要功能包括:
首先,搭建基本的项目结构,并划分组件。可以将整个应用划分为以下组件:
TodoList
:显示所有待办事项的列表TodoItem
:显示单个待办事项TodoForm
:用于添加新的待办事项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 | <!DOCTYPE html> < html > < head > < meta charset = "UTF-8" > < title >简单待办事项应用</ title > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://cdn.jsdelivr.net/npm/vue@2" ></ script > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://unpkg.com/vuex@3" ></ script > </ head > < body > < div id = "app" > < todo-form ></ todo-form > < todo-list ></ todo-list > </ div > < script > Vue.component('todo-form', { template: ` < div > < input v-model = "newTodo" placeholder = "添加新事项" /> < button v-on:click = "addTodo" >添加</ button > </ div > `, data: function() { return { newTodo: '' } }, methods: { addTodo: function() { if (this.newTodo.trim()) { app.$store.dispatch('addTodo', this.newTodo); this.newTodo = ''; } } } }); Vue.component('todo-list', { template: ` < ul > < li v-for = "todo in todos" :class = "{ completed: todo.completed }" v-on:click = "toggleTodo(todo)" > {{ todo.text }} </ li > </ ul > `, computed: { todos: function() { return this.$store.state.todos; } }, methods: { toggleTodo: function(todo) { app.$store.dispatch('toggleTodo', todo); } } }); const store = new Vuex.Store({ state: { todos: [] }, mutations: { addTodo(state, todo) { state.todos.push({ text: todo, completed: false }); }, toggleTodo(state, todo) { todo.completed = !todo.completed; } } }); var app = new Vue({ el: '#app', store }); </ script > </ body > </ html > |
在上面的代码中,TodoForm
组件负责添加新的待办事项,而TodoList
组件负责显示所有待办事项,并提供标记已完成或未完成的功能。
可以进一步调试代码,确保每个功能都能正确工作。例如,在浏览器的开发者工具中查看控制台输出,确保数据能够正确地存储和更新。
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 | <!DOCTYPE html> < html > < head > < meta charset = "UTF-8" > < title >简单待办事项应用</ title > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://cdn.jsdelivr.net/npm/vue@2" ></ script > < script class = "lazyload" src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original = "https://unpkg.com/vuex@3" ></ script > </ head > < body > < div id = "app" > < todo-form ></ todo-form > < todo-list ></ todo-list > </ div > < script > Vue.component('todo-form', { template: ` < div > < input v-model = "newTodo" placeholder = "添加新事项" /> < button v-on:click = "addTodo" >添加</ button > </ div > `, data: function() { return { newTodo: '' } }, methods: { addTodo: function() { if (this.newTodo.trim()) { app.$store.dispatch('addTodo', this.newTodo); this.newTodo = ''; } } } }); Vue.component('todo-list', { template: ` < ul > < li v-for = "todo in todos" :class = "{ completed: todo.completed }" v-on:click = "toggleTodo(todo)" > {{ todo.text }} </ li > </ ul > `, computed: { todos: function() { return this.$store.state.todos; } }, methods: { toggleTodo: function(todo) { app.$store.dispatch('toggleTodo', todo); } } }); const store = new Vuex.Store({ state: { todos: [] }, mutations: { addTodo(state, todo) { state.todos.push({ text: todo, completed: false }); }, toggleTodo(state, todo) { todo.completed = !todo.completed; } } }); var app = new Vue({ el: '#app', store }); </ script > </ body > </ html > |