Vue 知识点总结 - 基本使用、高级特性

发布时间:2024年01月03日

Vue 基本使用

插值、表达式

<!-- 插值 {{}} -->
<span>{{ message }}</span>

<!-- 使用表达式 -->
<span>{{ number + 1 }}</span>
<span>{{ ok ? 'YES' : 'NO' }}</span>
<span>{{ message.split('').reverse().join('') }}</span>

指令、动态属性

v-html

  • 会覆盖子组件。
  • 会有XSS风险。

class 和 style

  • 使用动态属性 v-bind: 简写:
  • style 对象属性使用驼峰式写法
<template>
	<p :class="{ black: isBlack, yellow: isYellow }">使用 class 对象</p>
	<p :class="[black, yellow]">使用 class 数组</p>
	<p :style="styleData">使用 style</p>
</template>
export default {
    data() {
        return {
            isBlack: true,
            isYellow: true,
            black: 'black',
            yellow: 'yellow',
            styleData: {
                fontSize: '40px',
                color: 'red',
                backgroundColor: '#ccc'
            }
        };
    }
}

条件渲染

v-ifv-else 的用法:可以使用变量,也可使用 === 表达式。

<template>
    <div>
        <p v-if="type === 'a'">A</p>
        <p v-else-if="type === 'b'">B</p>
        <p v-else>other</p>

        <p v-show="type === 'a'">A by v-show</p>
        <p v-show="type === 'b'">B by v-show</p>
    </div>
</template>
export default {
    data() {
        return {
            type: 'a'
        };
    }
}

v-ifv-show的区别?

  • v-if 控制dom节点的渲染和销毁,适用于切换不频繁的场景;
  • v-show是通过display: none;来控制显示隐藏,适用于切换频繁的场景。

循环(列表)渲染

  • v-for遍历,需要写key(尽量不要是randomindex,需要是和业务相关的id);
  • v-forv-if不能同时使用。
<template>
    <div>
        <p>遍历数组</p>
        <ul>
            <li v-for="(item, index) in listArr" :key="item.id">
                {{index}} - {{item.id}} - {{item.title}}
            </li>
        </ul>

        <p>遍历对象</p>
        <ul >
            <li v-for="(val, key, index) in listObj" :key="key">
                {{index}} - {{key}} -  {{val.title}}
            </li>
        </ul>
    </div>
</template>
export default {
    data() {
        return {
            flag: false,
            listArr: [
                { id: 'a', title: '标题1' }, // 数据结构中,最好有 id ,方便使用 key
                { id: 'b', title: '标题2' },
                { id: 'c', title: '标题3' }
            ],
            listObj: {
                a: { title: '标题1' },
                b: { title: '标题2' },
                c: { title: '标题3' },
            }
        }
    }
}

computed 和 watch

  • computed 有缓存,data 不变则不会重新计算。
  • watch 是浅度监听, watch监听引用类型,拿不到 oldval

watch 如何深度监听?

<template>
    <div>
        <input v-model="name"/>
        <input v-model="info.city"/>
    </div>
</template>
<script>
export default {
    data() {
        return {
            name: '章三',
            info: {
                city: '北京'
            }
        }
    },
    watch: {
        name(val, oldVal) {
            console.log('watch name', val, oldVal) // 值类型,可正常拿到 oldVal 和 val
        },
        info: {
            handler(val, oldVal) {
                console.log('watch info', val, oldVal) // 引用类型,拿不到 oldVal  因为指针相同,此时已经指向了新的 val
            },
            deep: true // 深度监听
        }
    }
}
</script>

事件

event 事件

  • 如果不需要传参,直接写函数名,可以在函数中获取到 event 参数;
  • 如果要传自定义参数,需要手动将event参数传递($event)。
<template>
    <div>
        <p>{{num}}</p>
        <button @click="increment1">+1</button>
        <button @click="increment2(2, $event)">+2</button>
    </div>
</template>
export default {
    data() {
        return {
            num: 0
        }
    },
    methods: {
        increment1(event) {
            // eslint-disable-next-line
            console.log('event', event, event.__proto__.constructor) // 是原生的 event 对象
            // eslint-disable-next-line
            console.log(event.target)
            // eslint-disable-next-line
            console.log(event.currentTarget) // 注意,事件是被注册到当前元素的,和 React 不一样
            this.num++

            // 1. event 是原生的
            // 2. 事件被挂载到当前元素
            // 和 DOM 事件一样
        },
        increment2(val, event) {
            // eslint-disable-next-line
            console.log(event.target)
            this.num = this.num + val
        },
        loadHandler() {
            // do some thing
        }
    },
    mounted() {
        window.addEventListener('load', this.loadHandler)
    },
    beforeDestroy() {
        //【注意】用 vue 绑定的事件,组建销毁时会自动被解绑
        // 自己绑定的事件,需要自己销毁!!!
        window.removeEventListener('load', this.loadHandler)
    }
}

vue中事件被绑定到哪里?

  • event是原生的;
  • 事件绑定到当前元素。

事件修饰符

修饰符可以串联;可以只有修饰符。

  • v-on:click.stop 阻止单击事件继续传播
  • v-on:submit.prevent 提交事件不再重载页面
  • v-on:click.capture 内部元素触发的事件先在此处理,然后才交由内部元素进行处理
  • v-on:click.self 只当在 event.target 是当前元素自身时触发处理函数
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a >
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a >
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

按键修饰符

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

表单

  • 使用 v-model
  • 常见的表单项:textareacheckboxradioselect
  • 修饰符:lazy(防抖,输完才会变化)、number(转换成数字)、trim(去掉两端空格)
<template>
    <div>
        <p>输入框: {{name}}</p>
        <input type="text" v-model.trim="name"/>
        <input type="text" v-model.lazy="name"/>
        <input type="text" v-model.number="age"/>

        <p>多行文本: {{desc}}</p>
        <textarea v-model="desc"></textarea>
        <!-- 注意,<textarea>{{desc}}</textarea> 是不允许的!!! -->

        <p>复选框 {{checked}}</p>
        <input type="checkbox" v-model="checked"/>

        <p>多个复选框 {{checkedNames}}</p>
        <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
        <label for="jack">Jack</label>
        <input type="checkbox" id="john" value="John" v-model="checkedNames">
        <label for="john">John</label>
        <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
        <label for="mike">Mike</label>

        <p>单选 {{gender}}</p>
        <input type="radio" id="male" value="male" v-model="gender"/>
        <label for="male"></label>
        <input type="radio" id="female" value="female" v-model="gender"/>
        <label for="female"></label>

        <p>下拉列表选择 {{selected}}</p>
        <select v-model="selected">
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>

        <p>下拉列表选择(多选) {{selectedList}}</p>
        <select v-model="selectedList" multiple>
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
    </div>
</template>
export default {
    data() {
        return {
            name: '章三',
            age: 18,
            desc: '自我介绍',

            checked: true,
            checkedNames: [],

            gender: 'male',

            selected: '',
            selectedList: []
        };
    }
}

Vue 组件的使用

vue 组件如何通讯

  • 父子组件通过 props 和 $event 通讯
  • 兄弟组件之间通过 自定义事件: o n 、 on、 onevent、$off
  • 所有组件之间可通过 vuex 通讯
// event.js
import Vue from 'vue';

export default new Vue();

<!-- 子组件 List.vue -->
<template>
    <div>
        <ul>
            <li v-for="item in list" :key="item.id">
                {{item.title}}

                <button @click="deleteItem(item.id)">删除</button>
            </li>
        </ul>
    </div>
</template>
// 子组件 List.vue
import event from './event';

export default {
    // props: ['list']
    props: {
        // prop 类型和默认值
        list: {
            type: Array,
            default() {
                return [];
            }
        }
    },
    data() {
        return {

        };
    },
    methods: {
        deleteItem(id) {
            this.$emit('delete', id);
        },
        addTitleHandler(title) {
            console.log('on add title', title);
        }
    },
    created() {
        console.log('list created');
    },
    mounted() {
        console.log('list mounted');

        // 绑定自定义事件
        event.$on('onAddTitle', this.addTitleHandler);
    },
    beforeUpdate() {
        console.log('list before update');
    },
    updated() {
        console.log('list updated');
    },
    beforeDestroy() {
        // 及时销毁,否则可能造成内存泄露
        event.$off('onAddTitle', this.addTitleHandler);
    }
}
<!-- 子组件 Input.vue -->
<template>
    <div>
        <input type="text" v-model="title"/>
        <button @click="addTitle">add</button>
    </div>
</template>
// 子组件 Input.vue
import event from './event';

export default {
    data() {
        return {
            title: ''
        };
    },
    methods: {
        addTitle() {
            // 调用父组件的事件
            this.$emit('add', this.title);

            // 调用自定义事件
            event.$emit('onAddTitle', this.title);

            this.title = '';
        }
    }
}
<!-- 父组件 Index.vue -->
<template>
    <div>
        <Input @add="addHandler"/>
        <List :list="list" @delete="deleteHandler"/>
    </div>
</template>
// 父组件 Index.vue
import Input from './Input';
import List from './List';

export default {
    components: {
        Input,
        List
    },
    data() {
        return {
            list: [
                {
                    id: 'id-1',
                    title: '标题1'
                },
                {
                    id: 'id-2',
                    title: '标题2'
                }
            ]
        };
    },
    methods: {
        addHandler(title) {
            this.list.push({
                id: `id-${Date.now()}`,
                title
            });
        },
        deleteHandler(id) {
            this.list = this.list.filter(item => item.id !== id);
        }
    },
    created() {
        console.log('index created');
    },
    mounted() {
        console.log('index mounted');
    },
    beforeUpdate() {
        console.log('index before update');
    },
    updated() {
        console.log('index updated');
    },
}

vue 组件生命周期

单个组件生命周期

  • 初始化阶段:beforeCreatecreatedvue实例初始化完成)
  • 挂载阶段:beforeMountmounteddom渲染完成,一般进行ajax请求)
  • 更新阶段:beforeUpdatedata改变,dom渲染之前)、updateddata改变,vdom重新渲染完成)
  • 销毁阶段:beforeDestroy(解除绑定,销毁子组件,解绑事件监听器)、destroyed
    在这里插入图片描述

父子组件生命周期

以上述“vue组件如何通讯”的代码作为例子讲解。
在这里插入图片描述
父组件初始化完成
子组件初始化完成

子组件挂载完成
父组件挂载完成

父组件开始更新
子组件开始更新
子组件更新完成
父组件更新完成

父组件开始销毁
子组件开始销毁
子组件销毁完成
父组件销毁完成

index created
list created

list mounted
index mounted

index before update
list before update
list updated
index updated

Vue 高级特性

自定义 v-model

<template>
    <!-- 例如:vue 颜色选择 -->
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)"
    >
    <!--
        1. 上面的 input 使用了 :value 而不是 v-model
        2. 上面的 change1 和 model.event 要对应起来
        3. text1 属性对应起来
    -->
</template>
export default {
    model: {
        prop: 'text1', // 对应 props text1
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return '';
        }
    }
}
<!-- 使用自定义 v-model -->
<template>
	<p>{{ name }}</p>
	<CustomVModel v-model="name"/>
</template>

$nextTick

由于vue是异步渲染,data改变之后,dom不会立刻渲染,$nextTick会在dom渲染之后被触发,以获取最新的dom节点。

<template>
  <div id="app">
    <ul ref="ul1">
        <li v-for="(item, index) in list" :key="index">
            {{item}}
        </li>
    </ul>
    <button @click="addItem">添加一项</button>
  </div>
</template>
export default {
  name: 'app',
  data() {
      return {
        list: ['a', 'b', 'c'];
      };
  },
  methods: {
    addItem() {
        this.list.push(`${Date.now()}`);
        this.list.push(`${Date.now()}`);
        this.list.push(`${Date.now()}`);

        // 1. 异步渲染,$nextTick 待 DOM 渲染完再回调
        // 3. 页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次
        this.$nextTick(() => {
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1;
   
          console.log( ulElem.childNodes.length );
        })
    }
  }
}

slot 插槽

父组件想往子组件内部插一些东西。

基本使用

<!-- SlotDemo.vue -->
<template>
    <a :href="url">
        <slot>
            默认内容,即父组件没设置内容时,这里显示
        </slot>
    </a>
</template>
// SlotDemo.vue
export default {
    props: ['url'],
    data() {
        return {};
    }
}
<!-- Index.vue -->
<template>
	<SlotDemo :url="website.url">
         {{website.title}}
    </SlotDemo>
</template>
// Index.vue
import SlotDemo from './SlotDemo';

export default {
    components: {
        SlotDemo
    },
    data() {
        return {
            name: '章三',
            website: {
                url: 'http://imooc.com/',
                title: 'imooc',
                subTitle: '程序员的梦工厂'
            },
            showFormDemo: false
        }
    }
}

作用域插槽

把子组件的data扔出来,让父组件获取到。
子组件的<slot>指定:slotData将数据暴露出去;父组件通过v-slot定义一个名字xxx,然后通过xxx.slotData获取到子组件暴露出去的数据。

<!-- ScopedSlotDemo.vue -->
<template>
    <a :href="url">
        <slot :slotData="website">
            {{website.subTitle}} <!-- 默认值显示 subTitle ,即父组件不传内容时 -->
        </slot>
    </a>
</template>
// ScopedSlotDemo.vue
export default {
    props: ['url'],
    data() {
        return {
            website: {
                url: 'http://wangEditor.com/',
                title: 'wangEditor',
                subTitle: '轻量级富文本编辑器'
            }
        };
    }
}
<!-- Index.vue -->
<template>
	<ScopedSlotDemo :url="website.url">
        <template v-slot="slotProps">
            {{slotProps.slotData.title}}
        </template>
    </ScopedSlotDemo>
</template>
// Index.vue
import ScopedSlotDemo from './ScopedSlotDemo';

export default {
    components: {
        ScopedSlotDemo
    },
    data() {
        return {
            name: '章三',
            website: {
                url: 'http://imooc.com/',
                title: 'imooc',
                subTitle: '程序员的梦工厂'
            },
            showFormDemo: false
        }
    }
}

具名插槽

<!-- NamedSlotDemo.vue -->
<template>
	<div class="container">
		<header>
			<slot name="header"></slot>
		</header>
		<main>
			<slot></slot>
		</main>
		<footer>
			<slot name="footer"></slot>
		</footer>
	</div>
</template>
// NamedSlotDemo.vue
export default {
    props: {},
    data() {
        return {};
    }
}
<!-- Index.vue -->
<template>
	<NamedSlotDemo>
         <template v-slot:header>
         	<h1>将插入 header slot 中</h1>
         </template>

		 <p>将插入到 main slot 中,即未命名的 slot</p>

		 <template v-slot:footer>
         	<p>将插入 footer slot 中</p>
         </template>
    </NamedSlotDemo>
</template>
// Index.vue
import NamedSlotDemo from './NamedSlotDemo';

export default {
    components: {
        NamedSlotDemo
    },
    data() {
        return {};
    }
}

动态组件、异步组件

动态组件

用法::is="组件名字"
需要根据数据,动态渲染组件。即组件类型不确定。

<!-- NextTick.vue -->
<template>
  <div id="app">
    <ul ref="ul1">
        <li v-for="(item, index) in list" :key="index">
            {{item}}
        </li>
    </ul>
    <button @click="addItem">添加一项</button>
  </div>
</template>
// NextTick.vue
export default {
  name: 'app',
  data() {
      return {
        list: ['a', 'b', 'c']
      }
  },
  methods: {
    addItem() {
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)

        // 1. 异步渲染,$nextTick 待 DOM 渲染完再回调
        // 3. 页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次
        this.$nextTick(() => {
          // 获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        })
    }
  }
}
<!-- Index.vue -->
<template>
	<component :is="NextTickName"/> 
</template>
// Index.vue
import NextTick from './NextTick'

export default {
    components: {
        NextTick
    },
    data() {
        return {
        	NextTickName: 'NextTick' // 对应组件的名字
        };
    }
}

异步组件

用法:import()函数。
按需加载,异步加载大组件。

<!-- FormDemo.vue -->
<template>
    <div>
        <p>输入框: {{name}}</p>
        <input type="text" v-model.trim="name"/>
        <input type="text" v-model.lazy="name"/>
        <input type="text" v-model.number="age"/>

        <p>多行文本: {{desc}}</p>
        <textarea v-model="desc"></textarea>
        <!-- 注意,<textarea>{{desc}}</textarea> 是不允许的!!! -->

        <p>复选框 {{checked}}</p>
        <input type="checkbox" v-model="checked"/>

        <p>多个复选框 {{checkedNames}}</p>
        <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
        <label for="jack">Jack</label>
        <input type="checkbox" id="john" value="John" v-model="checkedNames">
        <label for="john">John</label>
        <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
        <label for="mike">Mike</label>

        <p>单选 {{gender}}</p>
        <input type="radio" id="male" value="male" v-model="gender"/>
        <label for="male"></label>
        <input type="radio" id="female" value="female" v-model="gender"/>
        <label for="female"></label>

        <p>下拉列表选择 {{selected}}</p>
        <select v-model="selected">
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>

        <p>下拉列表选择(多选) {{selectedList}}</p>
        <select v-model="selectedList" multiple>
            <option disabled value="">请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
    </div>
</template>
// FormDemo.vue
export default {
    data() {
        return {
            name: '章三',
            age: 18,
            desc: '自我介绍',

            checked: true,
            checkedNames: [],

            gender: 'male',

            selected: '',
            selectedList: []
        }
    }
}
<!-- Index.vue -->
<template>
	<FormDemo v-if="showFormDemo"/>
    <button @click="showFormDemo = true">show form demo</button>
</template>
// Index.vue
export default {
    components: {
        FormDemo: () => import('../BaseUse/FormDemo'),
    },
    data() {
        return {
        	showFormDemo: false
        };
    }
}

keep-alive

vue缓存组件。频繁切换,不需要重复渲染的时候使用,比如切换tab页。

<!-- KeepAlive.vue -->
<template>
    <div>
        <button @click="changeState('A')">A</button>
        <button @click="changeState('B')">B</button>
        <button @click="changeState('C')">C</button>

        <keep-alive> <!-- tab 切换 -->
            <KeepAliveStageA v-if="state === 'A'"/> <!-- v-show -->
            <KeepAliveStageB v-if="state === 'B'"/>
            <KeepAliveStageC v-if="state === 'C'"/>
        </keep-alive>
    </div>
</template>
// KeepAlive.vue
import KeepAliveStageA from './KeepAliveStateA'
import KeepAliveStageB from './KeepAliveStateB'
import KeepAliveStageC from './KeepAliveStateC'

export default {
    components: {
        KeepAliveStageA,
        KeepAliveStageB,
        KeepAliveStageC
    },
    data() {
        return {
            state: 'A'
        }
    },
    methods: {
        changeState(state) {
            this.state = state
        }
    }
}
<!-- KeepAliveStateA.vue -->
<template>
    <p>state A</p>
</template>
// KeepAliveStateA.vue
export default {
    mounted() {
        // eslint-disable-next-line
        console.log('A mounted')
    },
    destroyed() {
        // eslint-disable-next-line
        console.log('A destroyed')
    }
}
<!-- KeepAliveStateB.vue -->
<template>
    <p>state B</p>
</template>
// KeepAliveStateB.vue
export default {
    mounted() {
        // eslint-disable-next-line
        console.log('B mounted')
    },
    destroyed() {
        // eslint-disable-next-line
        console.log('B destroyed')
    }
}
<!-- KeepAliveStateC.vue -->
<template>
    <p>state C</p>
</template>
// KeepAliveStateC.vue
export default {
    mounted() {
        // eslint-disable-next-line
        console.log('C mounted')
    },
    destroyed() {
        // eslint-disable-next-line
        console.log('C destroyed')
    }
}
<!-- Index.vue -->
<template>
	<<KeepAlive /> 
</template>
// Index.vue
import KeepAlive from './KeepAlive';

export default {
    components: {
        KeepAlive
    },
    data() {
        return {
        };
    }
}

mixin

多个组件有相同的逻辑,抽离出来,就使用mixin
但是它会有一些问题,vue3提出来的composition API可以解决这些问题。

// mixin.js
export default {
    data() {
        return {
            city: '北京'
        }
    },
    methods: {
        showName() {
            // eslint-disable-next-line
            console.log(this.name)
        }
    },
    mounted() {
        // eslint-disable-next-line
        console.log('mixin mounted', this.name)
    }
}
<!-- MixinDemo.vue -->
<template>
    <div>
        <p>{{name}} {{major}} {{city}}</p>
        <button @click="showName">显示姓名</button>
    </div>
</template>
// MixinDemo.vue
import myMixin from './mixin'

export default {
    mixins: [myMixin], // 可以添加多个,会自动合并起来
    data() {
        return {
            name: '章三',
            major: 'web 前端'
        }
    },
    methods: {
    },
    mounted() {
        // eslint-disable-next-line
        console.log('component mounted', this.name)
    }
}

mixin的问题:

  1. 变量来源不明确,不利于阅读
  2. mixin可能造成命名冲突
  3. mixin组件可能会出现多对多的关系,复杂度较高

Vuex

vuexvue的状态管理库,方便组件之间的通讯。

图示

在这里插入图片描述

出处:https://coding.imooc.com/lesson/419.html

核心

  • state:状态树
  • getter:派生状态(也叫做store 的计算属性)
  • mutation:更改 store 中状态的唯一方法是提交 mutation
  • action :处理异步操作
  • module:由于单一状态比较臃肿,所以vuex支持将将 store 分割成模块。

关键属性

  • dispatch
    Action 通过 store.dispatch 方法触发。
  • commit
    提交 mutation更改store 中的状态。store.commit
  • mapState
    当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性。
  • mapGetters
    store 中的 getter 映射到局部计算属性。
  • mapActions
    在组件中分发action,可以使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store)。
  • mapMutations
    在组件中提交mutation,可以使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。

vue-router

路由模式

  1. hash模式:默认,如http://www.abc.com#/user/10
  2. h5 history 模式:需要server端支持,如http://www.abc.com/user/10

路由配置

动态路由

const User = {
	// 获取参数如 10 、20
	template: '<div>User {{ $route.params.id }}</div>'
};

const router = new VueRouter({
	routes: [
		// 动态路径参数:以冒号开头。
		// 能命中 '/user/10'、'/user/20' 等格式的路由
		{
			path: '/user/:id',
			componnet: User
		}
	]
});

懒加载

export default new VueRouter({
	routes: [
		{
			path: '/',
			component: () => import('./../components/Navigator')
		},
		{
			path: '/feedback',
			component: () => import('./../components/FeedBack')
		}
	]
});
文章来源:https://blog.csdn.net/sinat_39145919/article/details/135172260
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。