1.keep-alive #

在Vue 2中,keep-alive组件是用于缓存组件状态的。当组件被包裹在<keep-alive>标签中时,组件不会在路由变化时被销毁,而是被缓存起来。这样做的优点是可以保留组件状态,避免重新渲染,从而提高性能。

activateddeactivated 是专为<keep-alive>设计的生命周期钩子。

下面是一个简单的例子,演示了activateddeactivated如何使用,以及如何和<keep-alive>结合:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Router Demo with keep-alive</title>
</head>
<body>
    <div id="app">
        <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link>
        <keep-alive>
            <router-view></router-view>
        </keep-alive>
    </div>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
    <script>
        const Home = {
            template: '<div>Home Page</div>',
            activated() {
                console.log("Home component activated");
            },
            deactivated() {
                console.log("Home component deactivated");
            }
        };

        const About = {
            template: '<div>About Page</div>',
            activated() {
                console.log("About component activated");
            },
            deactivated() {
                console.log("About component deactivated");
            }
        };

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

        const router = new VueRouter({
            routes
        });

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

在这个例子中,当你在"Home"和"About"页面之间切换时,会在控制台中看到"activated"和"deactivated"的相关日志。由于组件被包裹在<keep-alive>中,因此它们的状态会被保留,而activateddeactivated生命周期钩子会在相应的时机被触发。

这样你可以在activated中添加一些逻辑,比如数据预拉取,或者在deactivated中添加一些清理逻辑。

2.native #

在 Vue 2.x 中,.native 修饰符用于侦听组件根元素的原生事件。默认情况下,当你在自定义组件上使用 v-on 侦听事件时,它只会侦听由该组件自身触发的事件。如果你想侦听由组件的根元素触发的原生事件,你需要使用 .native 修饰符。

在下面的例子中,我将添加一个名为 CustomButton 的自定义组件。这个组件有一个按钮,当该按钮被点击时,它会触发一个原生的 click 事件。然后,在主 Vue 应用程序中,我将使用 .native 修饰符来侦听这个事件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Native Event Demo</title>
</head>
<body>
    <div id="app">
        <!-- 使用.native修饰符侦听原生click事件 -->
        <custom-button @click.native="handleClick"></custom-button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        // 定义一个名为CustomButton的组件
        Vue.component('custom-button', {
            template: '<button>Click Me!</button>',
        });

        // 初始化Vue实例
        new Vue({
            el: '#app',
            methods: {
                handleClick() {
                    alert('Button clicked!');
                }
            }
        });
    </script>
</body>
</html>

在这个例子中,CustomButton 组件包含一个简单的按钮。在主 Vue 实例中,我使用 .native 修饰符侦听按钮的原生 click 事件,并在事件触发时执行 handleClick 方法,这将弹出一个警告框。

3.sync #

在 Vue 2.x 中,.sync 修饰符用于双向绑定一个 prop。这意味着如果子组件修改了这个 prop 的值,它也会反映到父组件中。

在子组件中,可以使用 $emit 方法触发一个事件来通知父组件更新这个 prop 的值。

下面的代码演示了一个简单的 Vue 2.x 项目,其中包括一个子组件,该子组件接收一个 count prop 并提供一个按钮来改变它。通过 .sync 修饰符,我们可以使 count 在父组件和子组件之间双向绑定。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue .sync Demo</title>
</head>
<body>
    <div id="app">
        <p>Count in parent: {{ count }}</p>
        <count-sync :count.sync="count"></count-sync>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        // 子组件
        Vue.component('count-sync', {
            props: ['count'],
            template: `<div>
                        <p>Count in child: {{ count }}</p>
                        <button @click="increment">Increment</button>
                      </div>`,
            methods: {
                increment() {
                    this.$emit('update:count', this.count + 1);
                }
            }
        });

        // 根实例
        new Vue({
            el: '#app',
            data: {
                count: 0
            }
        });
    </script>
</body>
</html>

在这个例子中:

这样,无论是在父组件还是在子组件中,count 都会保持同步。这就是 .sync 修饰符在 Vue 2.x 中的用法。

4.inheritAttrs #

在 Vue 2.x 中,inheritAttrs 是一个组件选项,用于控制父组件传给子组件的 attribute 是否会被应用在子组件的根元素上。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue inheritAttrs Demo</title>
</head>
<body>
    <div id="app">
        <h1>inheritAttrs Example</h1>
        <!-- Parent component passing attrs to child -->
        <child-component id="myId" data-info="additionalData"></child-component>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        // Define child component
        Vue.component('child-component', {
            inheritAttrs: false,  // Prevents 'id' and 'data-info' from appearing on root element
            template: `
                <div>
                    <p>Child component content.</p>
                    <!-- Explicitly bind inherited attributes to specific element -->
                    <span v-bind="$attrs">This element has inherited attributes.</span>
                </div>
            `
        });

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

在这个例子中:

5.errorHandler #

在 Vue 2.x 中,你可以使用 errorHandler 全局钩子函数来捕获组件内部的运行时错误。这个钩子函数会在 Vue 发现其下的组件层次中的错误时触发,使你能在一个集中的地方处理所有错误。

如何使用 errorHandler

你可以如下所示设置全局的 errorHandler

Vue.config.errorHandler = function (err, vm, info) {
  // err: 错误对象
  // vm: 出现错误的 Vue 组件
  // info: Vue 特定的错误信息,比如错误所在的生命周期钩子
  console.error('捕获到错误: ', err);
  console.error('出错的组件实例:', vm);
  console.error('更多信息:', info);
}

示例代码

在你给出的代码中添加 errorHandler

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Router Demo</title>
</head>
<body>
    <div id="app">

    </div>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
    <script>
        // 全局错误处理
        Vue.config.errorHandler = function (err, vm, info) {
          console.error('捕获到错误: ', err);
          console.error('出错的组件实例:', vm);
          console.error('更多信息:', info);
        };

        const Home = {
            template: '<div>Home</div>',
            created() {
                // 制造一个错误
                throw new Error('An error occurred in Home component!');
            }
        }

        const routes = [
            { path: '/', component: Home, meta: { scrollToTop: true } }
        ];
        const router = new VueRouter({
            routes
        });
        new Vue({
            el: '#app',
            router,
            methods: {}
        });
    </script>
</body>
</html>

在这个例子里,我特意在 Home 组件的 created 生命周期钩子中抛出了一个错误。由于我们已经设置了 errorHandler,所以这个错误会被 errorHandler 捕获,并且会打印出相应的错误信息和出错的组件实例。

这样,你可以在这个集中的地方对错误进行处理,比如发送错误报告等。

6.errorCaptured #

在 Vue 2.x 中,errorCaptured 是一个特殊的生命周期钩子,用于捕获子组件树(不包括其自身)中未捕获的错误。当子组件抛出一个错误,该错误会向上冒泡至最近的拥有 errorCaptured 钩子的父组件。

下面的代码示例演示了如何使用 errorCaptured

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Router Demo</title>
</head>
<body>
    <div id="app">
        <router-view></router-view>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script>
    <script>
        const Home = {
            template: '<div>Home Page</div>',
            created() {
                throw new Error("An error from Home component");
            }
        };

        const Parent = {
            template: `
                <div>
                    <h1>Parent Component</h1>
                    <router-view></router-view>
                </div>
            `,
            errorCaptured(err, vm, info) {
                console.log("Error captured in parent component: ", err);
                console.log("Component that caused the error: ", vm);
                console.log("Hook that caused the error: ", info);
                return false; // Stop the error from propagating further
            }
        };

        const routes = [
            { path: '/', component: Parent, children: [
                { path: '', component: Home }
            ], meta: { scrollToTop: true } }
        ];

        const router = new VueRouter({
            routes
        });

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

在这个例子中,我创建了三个组件:Home, Parent, 和 App(由 new Vue() 实例代表)。

Home 组件抛出错误时,Parent 组件的 errorCaptured 钩子将被触发,从而你可以在这里执行错误处理代码。我在这里简单地打印出错误信息和相关的组件和钩子信息。

注意:返回 false 会阻止错误进一步向上冒泡。如果你想让错误继续向上冒泡到其他祖先组件,可以返回 true 或不返回任何值。