为了账号安全,请及时绑定邮箱和手机立即绑定

Vue2 考点解析与实战攻略

标签:
Vue.js
概述

Vue2是一个轻量级的前端框架,本文全面介绍了Vue2的基础概念、核心特性、安装配置、数据绑定与指令、组件化开发、路由应用和状态管理等内容。文章还详细讲解了Vue2的重要考点,包括响应式系统和生命周期方法,帮助读者深入理解并掌握Vue2的关键知识点。

Vue2 基础概念入门

Vue2 简介

Vue.js 是一个轻量级的前端开源框架,由尤雨溪(Evan You)在2014年发布。Vue.js的设计灵感来源于AngularJS和React,但它的核心库只专注于视图层,体积小且易于集成到其他项目中。Vue.js特别注重用户体验,在开发者友好和性能上都有优异的表现。

Vue.js具备以下优点:

  1. 易于上手:Vue.js强调简洁性和易用性,对于新手来说非常友好。
  2. 双向数据绑定:Vue.js提供了双向数据绑定和指令,使视图和数据模型能够保持同步。
  3. 组件化开发:Vue.js支持组件化开发,可以将应用拆分成可复用的组件。
  4. 虚拟DOM:通过虚拟DOM提高性能,减少不必要的DOM操作。
  5. 插件生态系统:通过插件可以扩展核心功能,拥有丰富的插件生态系统。

Vue2 核心特性

Vue2的核心特性包括数据绑定、指令、组件化、虚拟DOM等。

  • 数据绑定:Vue2提供了双向数据绑定,使得视图和数据模型保持同步。v-model指令用于实现双向数据绑定。
  • 指令:Vue2内置了多个指令,如v-ifv-forv-bindv-on等,用于实现条件渲染、列表渲染、绑定属性和事件。
  • 组件化开发:Vue2支持组件化开发,可以将应用拆分成可复用的组件。
  • 虚拟DOM:Vue2使用虚拟DOM来提高性能,减少不必要的DOM操作。

Vue2 安装与配置

安装Vue2可以通过npm或直接引入CDN。下面是使用npm和CDN的方式。

  1. 创建一个新的Vue2项目,并通过npm安装Vue2:

    mkdir my-vue-app
    cd my-vue-app
    npm init -y
    npm install vue@2.6.14 --save
  2. 在项目中引入Vue.js(CDN引入方式):

    <!DOCTYPE html>
    <html>
    <head>
       <title>Vue2 Example</title>
       <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    </head>
    <body>
       <div id="app">
           {{ message }}
       </div>
       <script>
           var app = new Vue({
               el: '#app',
               data: {
                   message: 'Hello, Vue2!'
               }
           });
       </script>
    </body>
    </html>
  3. 配置项目(npm方式):

    • package.json中添加"start": "node server.js"
    • 创建server.js文件,使用Node.js来启动服务器。
    const http = require('http');
    const fs = require('fs');
    const path = require('path');
    const port = 8080;
    
    const server = http.createServer((req, res) => {
       const filePath = path.join(__dirname, `${req.url === '/' ? 'index.html' : req.url}`);
       const extname = path.extname(filePath);
       const contentType = {
           '.html': 'text/html',
           '.js': 'text/javascript'
       }[extname] || 'application/octet-stream';
    
       fs.readFile(filePath, (err, content) => {
           if (err) {
               res.writeHead(404, contentType);
               res.end('File not found');
           } else {
               res.writeHead(200, contentType);
               res.end(content);
           }
       });
    });
    
    server.listen(port, () => {
       console.log(`Server running on port ${port}`);
    });

在浏览器中访问http://localhost:8080即可看到Vue2的应用。

Vue2 数据绑定与指令详解

v-model 的使用

v-model是Vue2中用于实现双向数据绑定的指令。它可以绑定输入元素,使得输入框的内容与Vue实例中的数据进行双向同步。

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 v-model Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <input v-model="message">
        <p>{{ message }}</p>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello'
            }
        });
    </script>
</body>
</html>

在这个例子中,v-model绑定了message,当输入框中的内容改变时,message也会相应地更新。

v-bind 与 v-on 的应用

v-bind用于动态绑定HTML属性,如classid等。v-on用于绑定事件处理函数。

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 v-bind and v-on Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <button v-bind:class="{active: isActive}" v-on:click="onClick">
            Click me
        </button>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                isActive: false
            },
            methods: {
                onClick() {
                    this.isActive = !this.isActive;
                }
            }
        });
    </script>
</body>
</html>

在这个例子中,v-bind:class根据isActive的状态来动态绑定active类,v-on:click绑定点击事件的处理函数。

v-if 与 v-for 的条件渲染与列表渲染

v-if用于条件渲染,根据表达式的真假来决定元素是否显示。v-for用于列表渲染,遍历数组或对象来生成列表。

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 v-if and v-for Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <div v-if="show">
            <p>显示内容</p>
        </div>
        <ul>
            <li v-for="item in items">{{ item }}</li>
        </ul>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                show: true,
                items: ['苹果', '香蕉', '橙子']
            }
        });
    </script>
</body>
</html>

在这个例子中,v-if根据show的真假来决定是否显示内容,v-for遍历items数组来生成列表。

Vue2 组件化开发

组件基本概念

Vue2中的组件是一种可复用的Vue实例,可以被看作是自定义标签。组件可以有自己的数据、模板和逻辑,可以在应用中多次使用。

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 Components Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-component></my-component>
    </div>
    <script>
        Vue.component('my-component', {
            template: '<p>我是组件内容</p>'
        });

        var app = new Vue({
            el: '#app'
        });
    </script>
</body>
</html>

在这个例子中,定义了一个名为my-component的组件,其模版为<p>我是组件内容</p>

组件间通信

Vue2提供了父组件和子组件之间通信的几种方式,包括props$emitprovide/inject等。

  • Props

    父组件通过props属性向子组件传递数据。

    <!DOCTYPE html>
    <html>
    <head>
      <title>Vue2 Components Communication Example</title>
      <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    </head>
    <body>
      <div id="app">
          <my-component message="Hello from parent"></my-component>
      </div>
      <script>
          Vue.component('my-component', {
              props: ['message'],
              template: '<p>{{ message }}</p>'
          });
    
          var app = new Vue({
              el: '#app'
          });
      </script>
    </body>
    </html>

    父组件传递message给子组件,子组件通过props接收并渲染。

  • $emit

    子组件通过$emit向父组件传递数据。

    <!DOCTYPE html>
    <html>
    <head>
      <title>Vue2 Components Communication Example</title>
      <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    </head>
    <body>
      <div id="app">
          <my-component @message="handleMessage"></my-component>
      </div>
      <script>
          Vue.component('my-component', {
              template: '<p @click="sendMessage">点击我</p>',
              methods: {
                  sendMessage() {
                      this.$emit('message', 'Hello from child');
                  }
              }
          });
    
          var app = new Vue({
              el: '#app',
              methods: {
                  handleMessage(message) {
                      console.log(message);
                  }
              }
          });
      </script>
    </body>
    </html>

    子组件点击事件触发$emit,父组件通过@message监听并处理。

组件生命周期

Vue2的组件生命周期包括beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroydestroyed等。

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 Component Lifecycle Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <my-component></my-component>
    </div>
    <script>
        Vue.component('my-component', {
            template: '<p>组件内容</p>',
            data() {
                return {
                    message: 'Hello'
                };
            },
            beforeCreate() {
                console.log('beforeCreate');
            },
            created() {
                console.log('created');
            },
            beforeMount() {
                console.log('beforeMount');
            },
            mounted() {
                console.log('mounted');
            },
            beforeUpdate() {
                console.log('beforeUpdate');
            },
            updated() {
                console.log('updated');
            },
            beforeDestroy() {
                console.log('beforeDestroy');
            },
            destroyed() {
                console.log('destroyed');
            }
        });

        var app = new Vue({
            el: '#app'
        });
    </script>
</body>
</html>

在这个例子中,组件生命周期的各个阶段都被打印出来,显示了每个生命周期钩子的执行顺序。

Vue2 路由基础与实践

Vue Router 简介

Vue Router是Vue.js的官方路由插件,用于实现单页应用的路由功能。它允许应用程序根据不同的URL路径来加载不同的组件,实现页面跳转。

路由的基本配置

安装Vue Router:

npm install vue-router@3.4.9 --save

配置路由:

import Vue from 'vue';
import Router from 'vue-router';
import Home from './components/Home.vue';
import About from './components/About.vue';

Vue.use(Router);

const routes = [
    {
        path: '/',
        name: 'home',
        component: Home
    },
    {
        path: '/about',
        name: 'about',
        component: About
    }
];

const router = new Router({
    routes // 配置路由
});

export default router;

在Vue实例中使用路由:

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 Router Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue-router@3.4.9/dist/vue-router.js"></script>
    <script type="module" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="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: '<p>Home Page</p>'
        };

        const About = {
            template: '<p>About Page</p>'
        };

        const routes = [
            {
                path: '/',
                name: 'home',
                component: Home
            },
            {
                path: '/about',
                name: 'about',
                component: About
            }
        ];

        const router = new VueRouter({
            routes
        });

        var app = new Vue({
            el: '#app',
            router
        });
    </script>
</body>
</html>

在这个例子中,定义了两个路由,一个指向Home组件,一个指向About组件。<router-link>用于创建链接,<router-view>用于显示当前路由对应的组件。

路由参数与导航守卫

路由参数用于动态路由匹配,导航守卫用于在路由切换时执行一些操作。

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 Router Params and Guards Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue-router@3.4.9/dist/vue-router.js"></script>
</head>
<body>
    <div id="app">
        <router-link to="/">Home</router-link>
        <router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>
        <router-view></router-view>
    </div>
    <script>
        const Home = {
            template: '<p>Home Page</p>'
        };

        const User = {
            template: '<p>User Page ID: {{ $route.params.id }}</p>'
        };

        const routes = [
            {
                path: '/',
                name: 'home',
                component: Home
            },
            {
                path: '/user/:id',
                name: 'user',
                component: User
            }
        ];

        const router = new VueRouter({
            routes
        });

        router.beforeEach((to, from, next) => {
            console.log(`从 ${from.name} 跳转到 ${to.name}`);
            next();
        });

        var app = new Vue({
            el: '#app',
            router
        });
    </script>
</body>
</html>

在这个例子中,定义了一个带有动态参数的路由/user/:id,通过params传递参数。导航守卫router.beforeEach在每次路由切换时执行,打印出从哪个路由跳转到了哪个路由。

Vue2 状态管理与案例

Vuex 简介

Vuex是Vue.js的官方状态管理库,用于管理应用中的状态。它提供了一个集中式的存储,可以方便地管理和同步应用的状态。

Vuex 的基本使用

安装Vuex:

npm install vuex@3.6.0 --save

配置Vuex:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        increment(state) {
            state.count++;
        }
    },
    actions: {
        increment({ commit }) {
            commit('increment');
        }
    },
    getters: {
        count(state) {
            return state.count;
        }
    }
});

export default store;

在Vue实例中使用Vuex:

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 Vuex Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vuex@3.6.0/dist/vuex.js"></script>
    <script type="module" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="store.js"></script>
</head>
<body>
    <div id="app">
        <p>Count: {{ count }}</p>
        <button @click="increment">Increment</button>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            store,
            computed: {
                count() {
                    return this.$store.getters.count;
                }
            },
            methods: {
                increment() {
                    this.$store.dispatch('increment');
                }
            }
        });
    </script>
</body>
</html>

在这个例子中,定义了一个Vuex store,包括状态count、变异方法increment、动作increment和获取器count。在Vue实例中,通过computed属性和methods方法来访问和修改状态。

Vuex 项目实战

一个简单的购物车示例:

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 Vuex Shopping Cart Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vuex@3.6.0/dist/vuex.js"></script>
    <script type="module" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="store.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="item in cart" @click="removeItem(item)">
                {{ item.name }} - {{ item.quantity }}
            </li>
        </ul>
        <button @click="addItem">Add Item</button>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            store,
            computed: {
                cart() {
                    return this.$store.state.cart;
                }
            },
            methods: {
                addItem() {
                    this.$store.dispatch('addItem', { name: 'Item', quantity: 1 });
                },
                removeItem(item) {
                    this.$store.dispatch('removeItem', item);
                }
            }
        });
    </script>
</body>
</html>
// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        cart: []
    },
    mutations: {
        addItem(state, item) {
            state.cart.push(item);
        },
        removeItem(state, item) {
            state.cart = state.cart.filter(i => i.name !== item.name);
        }
    },
    actions: {
        addItem({ commit }, item) {
            commit('addItem', item);
        },
        removeItem({ commit }, item) {
            commit('removeItem', item);
        }
    }
});

export default store;

在这个例子中,定义了一个简单的购物车,包括增加商品和移除商品的动作。购物车的状态存储在Vuex中,通过computed属性和methods方法来访问和修改状态。

Vue2 常见面试题解析

Vue2 深拷贝与浅拷贝的区别

浅拷贝是指复制原始对象的引用,而不是复制对象本身。深拷贝是指复制原始对象及其所有子对象的副本。

let obj1 = { a: 1, b: 2 };
let obj2 = Object.assign({}, obj1); // 浅拷贝
obj1.b = 3;
console.log(obj2); // 输出 { a: 1, b: 3 }

let obj3 = JSON.parse(JSON.stringify(obj1)); // 深拷贝
obj1.b = 4;
console.log(obj3); // 输出 { a: 1, b: 2 }

在这个例子中,浅拷贝改变了原始对象的引用,深拷贝复制了原始对象及其所有子对象的副本。

Vue2 数据劫持原理

Vue2的数据劫持是通过Object.defineProperty来实现的。Object.defineProperty可以为对象的属性设置getter和setter,从而在属性读写时进行监听和操作。

function observe(obj) {
    for (let key in obj) {
        defineReactive(obj, key, obj[key]);
    }
}

function defineReactive(obj, key, val) {
    let dep = new Dep();
    Object.defineProperty(obj, key, {
        get() {
            Dep.target && dep.addDep(Dep.target);
            return val;
        },
        set(newVal) {
            if (newVal !== val) {
                val = newVal;
                dep.notify();
            }
        }
    });
}

function Dep() {
    this.deps = [];
}

Dep.prototype = {
    addDep(dep) {
        this.deps.push(dep);
    },
    notify() {
        this.deps.forEach(dep => dep.notify());
    }
};

let depId = 0;
function Dep(id) {
    this.id = id;
}

Dep.prototype = {
    notify() {
        console.log(`Dep ${this.id} notify`);
    }
};

let obj = { a: 1 };
observe(obj);
obj.a = 2; // 输出 Dep 0 notify

在这个例子中,observe函数遍历对象的属性,通过defineReactive为每个属性设置getter和setter。Dep用于管理依赖,Dep.target用于保存当前的依赖。

Vue2 的响应式与生命周期方法

Vue2的数据绑定是基于数据的响应式系统实现的。当数据发生变化时,Vue会自动更新视图。生命周期方法是在组件的不同生命周期阶段被调用的方法,用于在特定阶段执行一些操作。

<!DOCTYPE html>
<html>
<head>
    <title>Vue2 Lifecycle Example</title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <p>{{ message }}</p>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello'
            },
            beforeCreate() {
                console.log('beforeCreate');
            },
            created() {
                console.log('created');
            },
            beforeMount() {
                console.log('beforeMount');
            },
            mounted() {
                console.log('mounted');
            },
            beforeUpdate() {
                console.log('beforeUpdate');
            },
            updated() {
                console.log('updated');
            },
            beforeDestroy() {
                console.log('beforeDestroy');
            },
            destroyed() {
                console.log('destroyed');
            },
            methods: {
                changeMessage() {
                    this.message = 'World';
                }
            }
        });

        setTimeout(() => {
            app.changeMessage();
        }, 2000);
    </script>
</body>
</html>

在这个例子中,定义了Vue实例的生命周期方法,显示了每个生命周期钩子的执行顺序。当changeMessage方法被调用时,Vue会自动更新视图。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消