Vue.js组件
组件注册
? 全局注册
全局注册的组件在注册后可以用于任意实例或组件中。
注意:全局注册必须设置在根 Vue 实例创建之前
? 组件基础
本质上,组件是可复用的 Vue 实例,所以它们可与 new Vue 接收相同的选项,例如 data、methods 以及生命周期钩子等。
仅有的例外是像 el 这样根实例特有的选项:
组件具有两种命名规则:
kebab-case:'my-component’
PascalCase:'MyComponent'
组件命名规则:
Vue.component('my-component-a',{});
Vue.component('MyComponentB',{});
注意:无论采用哪种命名方式,在 DOM 中都只有 kebab-case 可以使用。
template 选项
template 选项用于设置组件的结构,最终被引入根实例或其他组件中
Vue.component('MyComA', {
template: `
<div>
这是组件 A 的内容: {{ 1 + 2 * 3 }}
</div>
`
});
注意:组件必须只有一个根元素。
data 选项
data 选项用于存储组件的数据,与根实例不同,组件的 data 选 项必须为函数,数据设置在返回值对象中。
Vue.component('MyComA', {
template: `
<div>
<h3>{{ title }}</h3>
<p>{{ content }}</p>
</div>
`,
data () {
return {
title: '这是组件标题',
content: '这是组件内容'
}
}
});
这种实现方式是为了确保每个组件实例可以维护一份被返回对象 的独立的拷贝,不会相互影响。
? 局部注册
局部注册的组件只能用在当前实例或组件中。
<div id="app">
<my-component-a></my-component-a>
<my-component-b></my-component-b>
</div>
var MyComponentA = {
template: `
<div>
<h3>{{ title }}</h3>
<p>{{ content }}</p>
</div>
`,
data () {
return {
title: '组件 A 标题',
content: '组件 A 内容'
}
}
};
var MyComponentB = {
template: `
<div>
<h3>{{ title }}</h3>
<p>{{ content }}</p>
</div>
`,
data () {
return {
title: '组件 B',
content: '组件 B 内容'
}
}
}
new Vue({
el: '#app',
data: {
},
components: {
'my-component-a': MyComponentA,
MyComponentB
}
});
组件通信
在组件间传递数据的操作,称为组件通信。
? 父组件向子组件传值
通过子组件的 props 选项接收父组件的传值 注意:props 不要与 data 存在同名属性 建议 prop 命名使用 camelCase,父组件绑定时使用 kebab-case
<div id="app">
<demo-item
v-for="item in items"
:item-title="item.title"
:item-content="item.content"
:key="item.title"
:item="item"
></demo-item>
</div>
Vue.component('demoItem', {
props: ['itemTitle', 'itemContent', 'item'],
template: `
<div>
<h3>{{ itemTitle }}</h3>
<p> {{ itemContent }} </p>
</div>
`
})
new Vue({
el: '#app',
data: {
items: [
{
title: '示例标题1',
content: '示例内容1'
},
{
title: '示例标题2',
content: '示例内容2'
},
{
title: '示例标题3',
content: '示例内容3'
},
]
}
})
单向数据流
父子组件间的所有 prop 都是单向下行绑定的。 如果子组件要处理 prop 数据,应当存储在 data 中后操作。 注意,如果 prop 为数组或对象时,子组件操作将会影响到父组件的状态。
<div id="app">
<my-component
:initial-title="title"
:obj="obj"
></my-component>
</div>
Vue.component('my-component', {
props: ['initialTitle', 'obj'],
template: `
<div>
{{ title }}
<button @click="fn">按钮</button>
</div>
`,
data () {
return {
title: this.initialTitle
}
},
methods: {
fn () {
this.obj.name = 'jack';
}
}
});
new Vue({
el: '#app',
data: {
title: '这是示例标题',
obj: {
name: 'william',
age: 18
}
}
});
Props 类型
Prop 可以设置类型检查,这时需要将 props 更改为一个带有验 证需求的对象,并指定对应类型。
prop 还可以同时指定多个类型,通过数组方式保存即可。
<div id="app">
<my-component
:par-str="str"
:par-num="num"
:par-arr="arr"
:par-obj="obj"
:par-any="any"
:par-data="str"
></my-component>
</div>
Vue.component('MyComponent', {
props: {
parStr: String,
parNum: Number,
parArr: Array,
parObj: Object,
parAny: undefined,
parData: [String, Boolean]
},
template: `
<div>
{{ parStr }}
{{ parNum }}
{{ parArr }}
{{ parObj }}
{{ parAny }}
{{ parData }}
</div>
`
})
new Vue({
el: '#app',
data: {
num: 100,
str: 'abc',
arr: [1, 2, 3],
obj: {
content1: '示例内容1',
content2: '示例内容2'
},
any: [1, 2, 3]
}
});
Props 验证 当 prop 需要设置多种规则时,可以将 prop 的值设置为选项对 象。 之前的类型检测功能通过 type 选项设置。
required 用于设置数据为必填项。 default 用于给可选项指定默认值,当父组件未传递数据时生效。 default 用于给可选项指定默认值,当父组件未传递数据时生效。 validator 用于给传入的 prop 设置校验函数,return 值为 false 时 Vue.js 会发出警告。 注意:验证函数中无法使用实例的 data、methods 等功能。
<div id="app">
<my-component
:par-str="str"
:par-num="num"
:par-num2="2000"
:par-arr="arr"
par-content="lagou: hello world"
></my-component>
</div>
Vue.component('MyComponent', {
props: {
parStr: {
type: String
},
parData: {
type: [Array, Object]
},
parNum: {
type: Number,
required: true
},
parNum2: {
type: Number,
default: 100
},
parArr: {
type: Array,
default () {
return [1, 2, 3];
}
},
parContent: {
type: String,
validator (value) {
console.log(this);
return value.startsWith('lagou');
}
}
},
template: `<div></div>`
})
new Vue({
el: '#app',
data: {
str: '示例内容',
num: 100,
arr: [10, 20, 30],
obj: {
content1: '内容1',
content2: '内容2'
}
}
});
非 Props 属性
当父组件给子组件设置了属性,但此属性在 props 中不存在,这 时会自动绑定到子组件的根元素上。
如果组件根元素已经存在了对应属性,则会替换组件内部的值。 class 与 style 是例外,当内外都设置时,属性会自动合并。
如果组件根元素已经存在了对应属性,则会替换组件内部的值。 class 与 style 是例外,当内外都设置时,属性会自动合并。
<div id="app">
<my-component
data-index="3"
:title="'示例标题内容'"
style="height: 200px;"
class="colorRed"
></my-component>
</div>
Vue.component('MyComponent', {
inheritAttrs: false,
template: `
<div data-index="6"
title="旧的title"
class="abc"
style="width: 200px;">
<p>这是组件的内容</p>
</div>
`
});
new Vue({
el: '#app',
data: {
}
});
? 子组件向父组件传值
子向父传值需要通过自定义事件实现。 子组件数据变化时,通过 $emit() 触发自定义事件。 自定义事件名称建议使用 kebab-case。 父组件监听子组件的自定义事件,并设置处理程序。
<div id="app">
<h3>购物车</h3>
<product-item
v-for="product in products"
:key="product.id"
:title="product.title"
@count-change="onCountChange"
></product-item>
<p>商品总个数为:{{ totalCount }}</p>
</div>
Vue.component('ProductItem', {
props: ['title'],
template: `
<div>
<span>商品名称: {{ title }}, 商品个数: {{ count }}</span>
<button @click="countIns1">+1</button>
<button @click="countIns5">+5</button>
</div>
`,
data () {
return {
count: 0
}
},
methods: {
countIns1 () {
this.$emit('count-change', 1);
this.count++;
},
countIns5 () {
this.$emit('count-change', 5);
this.count += 5;
}
}
});
new Vue({
el: '#app',
data: {
products: [
{
id: 1,
title: '苹果一斤'
},
{
id: 2,
title: '香蕉一根'
},
{
id: 3,
title: '橙子一个'
}
],
totalCount: 0
},
methods: {
onCountChange (productCount) {
this.totalCount += productCount;
}
}
});
自定义事件传值
子组件触发事件时可以向父组件传值。 父组件在监听事件时需要接收子组件传递的数据。
组件与 v-mode
v-model 用于组件时,需要通过 props 与自定义事件实现。
<div id="app">
<p>输入框内容为:{{ iptValue }}</p>
<com-input v-model="iptValue"></com-input>
</div>
var ComInput = {
props: ['value'],
template: `
<input
type="text"
:value="value"
@input="onInput"
>
`,
methods: {
onInput (event) {
this.$emit('input', event.target.value)
}
}
}
new Vue({
el: '#app',
data: {
iptValue: ''
},
components: {
ComInput
}
});
? 非父子组件传值
非父子组件指的是兄弟组件或完全无关的两个组件。
- 兄弟组件传值
兄弟组件可以通过父组件进行数据中转
- EventBus–非父子组件传值
当组件嵌套关系复杂时,根据组件关系传值会较为繁琐。 组件为了数据中转,data 中会存在许多与当前组件功能无关的数据。
EventBus (事件总线)是一个独立的事件中心,用于管理不同组件间的传值操作。
EventBus 通过一个新的 Vue 实例来管理组件传值操作,组件通过给实例注册事件、调用事件来实现数据传递。
发送数据的组件触发 bus 事件,接收的组件给 bus 注册对应事件。
给 bus 注册对应事件通过 $on() 操作。
最后创建根实例执行代码即可。
<div id="app">
<h3>购物车</h3>
<product-item></product-item>
<product-total></product-total>
</div>
Vue.component('ProductItem', {
template: `
<div>
<span>商品名称:苹果,商品个数:{{ count }}</span>
<button
@click="countIns"
>+1</button>
</div>
`,
data () {
return {
count: 0
}
},
methods: {
countIns () {
bus.$emit('countChange', 1);
this.count++;
}
}
});
Vue.component('ProductTotal', {
template: `
<p>总个数为: {{ totalCount }}</p>
`,
data () {
return {
totalCount: 0
}
},
created () {
bus.$on('countChange', (productCount) => {
this.totalCount += productCount;
});
}
})
new Vue({
el: '#app',
data: {
}
});
? 其他通信方式
- $root
$root 用于访问当前组件树根实例,设置简单的 Vue 应用时可以通过此方式进行组件传值。
除了 $root , Vue.js 中还提供了 $parent 与 $children 用于 便捷访问父子组件。
<div id="app">
<com-a></com-a>
</div>
var ComB = {
template: `
<div>
组件B: {{ $root.count }}
<button @click="clickFn">按钮</button>
</div>
`,
methods: {
clickFn () {
this.$root.count = 200;
}
}
};
var ComA = {
template: `
<div>
组件A: {{ $root.count }}
<button @click="clickFn">按钮</button>
<com-b></com-b>
</div>
`,
methods: {
clickFn () {
this.$root.count = 100;
}
},
components: {
ComB
}
};
new Vue({
el: '#app',
data: {
count: 0
},
components: {
ComA
}
});
- $refs
$refs 用于获取设置了 ref 属性的 HTML 标签或子组件 给普通 HTML 标签设置 ref 属性,$refs 可以获取 DOM
给子组件设置 ref 属性,渲染后可通过 $refs 获取子组件实例。
<div id="app">
<input type="text" ref="inp">
<button @click="fn">按钮</button>
<com-a ref="comA"></com-a>
</div>
var ComA = {
template: `<div>组件A的内容:{{ value }}</div>`,
data () {
return {
value: '示例内容'
}
}
}
var vm = new Vue({
el: '#app',
methods: {
fn () {
this.$refs.inp.focus();
this.$refs.comA.value = '新的内容';
}
},
components: {
ComA
},
mounted () {
console.log(this.$refs);
this.$refs.comA.value = "修改后的内容";
},
});
组件插槽
? 单个插槽 要通过 <slot> 进行插槽设置
Vue.component('ComA', {
template: `
<div>
<h3>组件标题</h3>
<slot>
这是插槽的默认内容
</slot>
</div>
`,
data () {
return {
value: '子组件的数据'
}
}
});
new Vue({
el: '#app',
data: {
parValue: '这是父组件的数据'
}
})
? 具名插槽 如果组件中有多个位置需要设置插槽,据需要给 设置 name,称为具名插槽。
<div id="app">
<com-a>
<template v-slot:header>
<h3>组件的头部内容</h3>
</template>
<p>组件的主体内容1</p>
<p>组件的主体内容2</p>
<template #footer>
<p>组件底部内容</p>
</template>
</com-a>
</div>
Vue.component('ComA', {
template: `
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
`
});
new Vue({
el: '#app',
data: {
}
});
? 作用域插槽
用于让插槽可以使用子组件的数据。
组件将需要被插槽使用的数据通过 v-bind 绑定给 ,这种 用于给插槽传递数据的属性称为插槽 prop
组件绑定数据后,插槽中需要通过 v-slot 接收数据。
<div id="app">
<com-a>
<template v-slot:default="dataObj">
{{ dataObj.value }}
{{ dataObj.num }}
</template>
<template v-slot:footer="dataObj">
{{ dataObj.value }}
</template>
</com-a>
<com-b #default="dataObj">
{{ dataObj }}
</com-b>
<com-b v-slot="{ value, num }">
{{ value }}
{{ num }}
</com-b>
</div>
var ComB = {
template: `
<div>
<p>组件B的内容: </p>
<slot
:value="value"
:num="num"
></slot>
</div>
`,
data () {
return {
value: '这是组件B内部的数据',
num: 200
}
}
};
var ComA = {
template: `
<div>
<p>组件A的内容: </p>
<slot
v-bind:value="value"
:num="num"
></slot>
<slot name="footer"
:value="value"
></slot>
</div>
`,
data () {
return {
value: '这是组件A内部的数据',
num: 100
}
}
};
new Vue({
el: '#app',
components: {
ComA, ComB
}
});
内置组件
? 动态组件
动态组件适用于多个组件频繁切换的处理。 <component> 用于将一个‘元组件’渲染为动态组件,以 is 属 性值决定渲染哪个组件。 is 属性会在每次切换组件时,Vue 都会创建一个新的组件实例。
<div id="app">
<button
v-for="title in titles"
:key="title"
@click="currentCom = title"
>
{{ title }}
</button>
<component :is="currentCom"></component>
</div>
var ComA = {
template: `<p>这是组件A的内容:<input type="text"></p>`
};
var ComB = {
template: `<p>这是组件B的内容:<input type="text"></p>`
};
var ComC = {
template: `<p>这是组件C的内容:<input type="text"></p>`
};
new Vue({
el: '#app',
data: {
titles: ['ComA', 'ComB', 'ComC'],
currentCom: 'ComA'
},
components: {
ComA, ComB, ComC
}
});
? keep-alive 组件
主要用于保留组件状态或避免组件重新渲染。
include 属性用于指定哪些组件会被缓存,具有多种设置方式 exclude 属性用于指定哪些组件不会被缓存。
max 属性用于设置最大缓存个数。
<div id="app">
<button
v-for="title in titles"
:key="title"
@click="currentCom = title"
>
{{title}}
</button>
<keep-alive max="2">
<component :is="currentCom"></component>
</keep-alive>
</div>
var ComA = {
template: `
<div>
请选择主食:
<br>
<label for="mantou">馒头:</label>
<input id="mantou" type="radio" name="zhushi" value="mantou">
<br>
<label for="mifan">米饭:</label>
<input id="mifan" type="radio" name="zhushi" value="mifan">
</div>
`
};
var ComB = {
template: `
<div>
请选择菜品:
<br>
<label for="luobo">炒萝卜:</label>
<input id="luobo" type="checkbox" name="cai" value="luobo">
<br>
<label for="niurou">炒牛肉:</label>
<input id="niurou" type="checkbox" name="cai" value="niurou">
<br>
<label for="pingguo">炒苹果:</label>
<input id="pingguo" type="checkbox" name="cai" value="pingguo">
</div>
`
};
var ComC = {
template: `
<div>
请选择汤:
<br>
<label for="tang1"">西红柿鸡蛋汤:</label>
<input id="tang1"" type="radio" name="tang" value="tang1"">
<br>
<label for="tang2">紫菜蛋花汤:</label>
<input id="tang2" type="radio" name="tang" value="tang2">
<br>
<label for="tang3">清汤</label>
<input id="tang3" type="radio" name="tang" value="tang3">
</div>
`
};
var ComD = {
template: `
<div>
请输入支付信息:
<br>
<label for="account"">请输入账号:</label>
<input id="account"" type="text" name="account">
<br>
<label for="password">请输入密码:</label>
<input id="password" type="password" name="password">
<br>
</div>
`
};
new Vue({
el: '#app',
data: {
titles: ['ComA', 'ComB', 'ComC', 'ComD'],
currentCom: 'ComA'
},
components: {
ComA, ComB, ComC, ComD
}
});
? 过渡组
用于在 Vue 插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡、动画效果.
? transition 组件
用于给元素和组件添加进入/离开过渡:
组件提供了 6个 class,用于设置过渡具体效果
.v-leave-to {
opacity: 0;
}
.v-leave-active {
transition: opacity 1s;
}
.v-enter {
opacity: 0;
}
.v-enter-to {
opacity: 0.5;
}
.v-enter-active {
transition: all 1s;
}
<div id="app">
<button @click="show = !show">切换</button>
<transition>
<p v-if="show">hello world</p>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
show: true
}
});
</script>
相关属性
给组件设置 name 属性,可用于给多个元素、组件设置不同的过 渡效果,这时需要将 v- 更改为对应 name- 的形式
.v-enter, .v-leave-to {
opacity: 0;
}
.v-enter-active, .v-leave-active {
transition: opacity .5s;
}
.demo-enter, .demo-leave-to {
opacity: 0;
transform: translateX(200px);
}
.demo-enter-active, .demo-leave-active {
transition: all .5s;
}
<button @click="show = !show">切换1</button>
<transition appear>
<p v-if="show">这是要切换的元素1</p>
</transition>
<br>
<button @click="showDemo = !showDemo">切换2</button>
<transition
name="demo"
appear
>
<p v-if="showDemo">这是要切换的元素2</p>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
show: true,
showDemo: true
}
});
</script>
? 自定义过渡类名 自定义类名比普通类名优先级更高,在使用第三方 CSS 动画库时非常有用
自定义过渡类名
用于设置自定义过渡类名的属性如下: ? enter-class ? enter-active-class ? enter-to-class ? leave-class ? leave-active-class ? leave-to-class
用于设置初始过渡类名的属性如下: ? appear-class ? appear-to-class ? appear-active-class
Animate.css 是一个第三方 CSS 动画库,通过设置类名来给元素添加各种动画效果。 使用注意: ? animate__ 前缀与 compat 版本 ? 基础类名 animate
<style>
.v-enter, .v-leave-to {
opacity: 0;
}
.v-enter-active, .v-leave-active {
transition: all .5s;
}
.test {
transition: all 3s;
}
</style>
</head>
<body>
<div id="app">
<button @click="show = !show">切换</button>
<transition
enter-active-class="test"
leave-active-class="test"
>
<p v-if="show">这是 p 标签</p>
</transition>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
show: true
}
});
</script>
? transition-group 组件
<transition-group> 用于给列表统一设置过渡动画。 ? tag 属性用于设置容器元素,默认为 。 ? 过渡会应用于内部元素,而不是容器。 ? 子节点必须有独立的 key,动画才能正常工作。
当列表元素变更导致元素位移,可以通过 .v-move 类名设置移动时的效果
ul {
position: relative;
}
.v-enter, .v-leave-to {
opacity: 0;
transform: translateX(100px);
}
.v-enter-active, .v-leave-active {
transition: all .5s;
}
/* 让元素在离场的过程中脱离标准流 */
.v-leave-active {
position: absolute;
}
.v-move {
transition: all .5s;
}
</style>
</head>
<body>
<div id="app">
<input type="text"
v-model="newTitle"
@keyup.enter="addItem"
>
<transition-group
tag="ul"
>
<li
v-for="item in items"
:key="item.id"
@click="removeItem(item)"
>
{{ item.title }}
</li>
</transition-group>
</div>
<script src="./lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
items: [
{ id: 1, title: '示例内容1'},
{ id: 2, title: '示例内容2'},
{ id: 3, title: '示例内容3'},
{ id: 4, title: '示例内容4'},
{ id: 5, title: '示例内容5'},
],
newTitle: '',
latestId: 5
},
methods: {
addItem () {
this.items.push({
id: this.latestId + 1,
title: this.newTitle
});
this.latestId++;
this.newTitle = '';
},
removeItem (item) {
var i = this.items.indexOf(item);
this.items.splice(i, 1);
}
}
});
</script>
Vue Router
Vue Router 是 Vue.js 的官方插件,用来快速实现单页应用。
单页应用
SPA(Single Page Application)单页面应用程序,简称单页应用。 指的是网站的 “所有” 功能都在单个页面中进行呈现。 具有代表性的有后台管理系统、移动端、小程序等。
优点: ? 前后端分离开发,提高了开发效率。 ? 业务场景切换时,局部更新结构。 ? 用户体验好,更加接近本地应用。
缺点: ? 不利于 SEO。 ? 初次首屏加载速度较慢。 ? 页面复杂度比较高。
前端路由
前端路由,指的是 URL与内容间的映射关系
? Hash 方式
通过 hashchange 事件监听 hash 变化,并进行网页内容更新
特点总结: ? Hash 方式兼容性好。 ? 地址中具有 #,不太美观。 ? 前进后退功能较为繁琐。
<div>
<a href="#/">首页</a>
<a href="#/category">分类页</a>
<a href="#/user">用户页</a>
</div>
<div id="container">
这是首页功能
</div>
var router = {
routes: {},
route: function (path, callback) {
this.routes[path] = callback;
},
init: function () {
var that = this;
window.onhashchange = function () {
var hash = location.hash.replace('#', '');
that.routes[hash] && that.routes[hash]();
};
}
};
var container = document.getElementById('container');
router.route('/', function () {
container.innerHTML = '这是首页功能';
});
router.route('/category', function () {
container.innerHTML = '这是分类功能';
});
router.route('/user', function () {
container.innerHTML = '这是用户功能';
});
router.init();
?History 方式
History 方式采用 HTML5 提供的新功能实现前端路由 在操作时需要通过 history.pushState() 变更 URL并执行对应操 作。
var router = {
routes: {},
route (path, callback) {
this.routes[path] = callback;
},
go (path) {
history.pushState({ path: path }, null, path);
this.routes[path] && this.routes[path]();
},
init () {
var that = this;
window.addEventListener('popstate', function (e) {
var path = e.state ? e.state.path : '/';
that.routes[path] && that.routes[path]();
});
}
};
router.init();
var links = document.querySelectorAll('a');
var container = document.querySelector('#container');
links.forEach(function (ele) {
ele.addEventListener('click', function (event) {
router.go(this.getAttribute('href'));
event.preventDefault();
});
});
router.route('/', function () {
container.innerHTML = '首页功能';
});
router.route('/category', function () {
container.innerHTML = '分类功能';
});
router.route('/user', function () {
container.innerHTML = '用户功能';
});
Vue Router
是 Vue.js 官方的路由管理器,让构建单页面应用变得易如反掌。 ? 基本使用
直接下载 / CDN
? 最新版本:https://unpkg.com/vue-router/dist/vue-router.js ? 指定版本:https://unpkg.com/vue-router@3.4.9/dist/vue-router.js
npm ? npm install vue-router
Vue Router 提供了用于进行路由设置的组件 <router-link> 与 <router-view>。
<div id="app">
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
var Index = {
template: `<div>首页功能</div>`
};
var User = {
template: `<div>用户功能</div>`
};
var Category = {
template: `<div>分类功能</div>`
};
var routes = [
{ path: '/', component: Index },
{ path: '/user', component: User },
{ path: '/category', component: Category }
];
var router = new VueRouter({
routes
});
var vm = new Vue({
el: '#app',
});
console.log(vm);
</script>
命名视图
如果导航后,希望同时在同级展示多个视图(组件),这时就需 要进行命名视图。 路由中通过 components 属性进行设置不同视图的对应组件。
<div id="app">
<router-link to="/">首页</router-link>
<router-link to="/user">用户</router-link>
<router-view name="sidebar"></router-view>
<router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
var SideBar1 = {
template: `<div>侧边栏1功能</div>`
};
var SideBar2 = {
template: `<div>侧边栏2功能</div>`
};
var Index = {
template: `<div>首页功能</div>`
};
var User = {
template: `<div>用户功能</div>`
};
var routes = [
{
path: '/',
components: {
default: Index,
sidebar: SideBar1
}
},
{
path: '/user',
components: {
default: User,
sidebar: SideBar2
}
}
];
var router = new VueRouter({
routes
});
new Vue({
el: '#app',
router
});
</script>
? 动态路由
当我们需要将某一类 URL 都映射到同一个组件,就需要使用动态路由。 定义路由规则时,将路径中的某个部分使用 : 进行标记,即可 设置为动态路由。 设置为动态路由后,动态部分为任意内容均跳转到同一组件。 : 部分对应的信息称为路径参数,存储在 vm.$route.params 中。
<div id="app">
<router-link to="/user/1">用户1</router-link>
<router-link to="/user/2">用户2</router-link>
<router-link to="/user/3">用户3</router-link>
<router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
var User = {
template: `<div>这是用户 {{ $route.params.id }} 的功能</div>`
};
var routes = [
{
path: '/user/:id', component: User
}
];
var router = new VueRouter({ routes });
var vm = new Vue({
el: '#app',
router
});
</script>
侦听路由参数
如果要响应路由的参数变化,可以通过 watch 监听 $route
var User = {
template: `
<div>
这是用户 {{ $route.params.id }} 的功能
<input type="text">
</div>`,
watch: {
$route (route) {
console.log(route.params.id)
}
}
};
var routes = [
{
path: '/user/:id', component: User
}
];
var router = new VueRouter({ routes });
var vm = new Vue({
el: '#app',
router
});
路由传参处理
这里通过路由的 props 设置数据,并通过组件 props接收 包含多个命名视图时,需要将路由的 props 设置为对象 如果希望设置静态数据,可将 props 中的某个组件对应的选项设 置为对象,内部属性会绑定给组件的 props
var User = {
template: `<div>这是用户 {{ $route.params.id }} 功能</div>`
};
var Category = {
props: ['id'],
template: `<div>这是分类 {{ id }} 功能</div>`
};
var routes = [
{
path: '/user/:id',
component: User
},
{
path: '/category/:id',
component: Category,
props: true
}
];
var router = new VueRouter({ routes });
var vm = new Vue({
el: '#app',
router
});
? 嵌套路由
实际场景中,路由通常由多层嵌套的组件组合而成,这时需要使用嵌套路由配置。
使用 children 来进行嵌套路由中的子路由设置
<div id="app">
<router-link to="/user">用户功能</router-link>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
var User = {
template: `
<div>
<h3>这是 User 组件的功能</h3>
<router-link to="/user/hobby">爱好功能</router-link>
<router-link to="/user/info">用户信息</router-link>
<router-view></router-view>
</div>
`
};
var UserHobby = {
template: `<div> UserHobby 组件</div>`
};
var UserInfo = {
template: `
<div>
UserInfo 组件
<router-link to="/user/info/school">学校信息</router-link>
<router-view></router-view>
</div>`
};
var UserInfoSchool = {
template: `<div> UserInfoSchool 组件</div>`
};
var routes = [
{
path: '/user',
component: User,
children: [
{
path: 'hobby',
component: UserHobby
},
{
path: 'info',
component: UserInfo,
children: [
{
path: 'school',
component: UserInfoSchool
},
]
}
]
}
];
var router = new VueRouter({ routes });
var vm = new Vue({
el: '#app',
router
});
</script>
? 编程式导航(通过方法设置导航)
router.push() 用来导航到一个新 URL <router-link> 的 to 属性使用绑定方式时也可属性对象结
<div id="app">
<router-link :to="{ path: '/user/700' }">用户700</router-link>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
var User = {
template: `<div> 这是用户 {{ $route.params.id }} </div>`
};
var routes = [
{
path: '/user/:id',
component: User
}
];
var router = new VueRouter({ routes });
var vm = new Vue({
el: '#app',
router
});
</script>
命名路由 设置路由时添加 name 属性 在 push() 中通过 name 导航到对应路由,参数通过 params 设 置。 也可以在 <router-link> 中使用
<div id="app">
<router-link :to="{ name: 'school', params: { id: 10 } }">学校10</router-link>
<router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
var School = {
template: `<div>School 组件的功能: {{ $route.params }}</div>`
};
var routes = [
{
path: '/user/:id/info/school',
name: 'school',
component: School
}
];
var router = new VueRouter({ routes });
var vm = new Vue({
el: '#app',
router
});
</script>
重定向
<div id="app">
<router-link to="/">首页</router-link>
<router-link to="/category/2">分类2</router-link>
<router-link to="/category"> /category </router-link>
<router-view></router-view>
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/vue-router.js"></script>
<script>
var Index = {
template: `<div>首页功能</div>`
};
var Category = {
template: `<div>分类 {{ $route.params.id }} 功能</div>`
};
var router = new VueRouter({
routes: [
{
path: '/',
component: Index
},
{
path: '/category/:id',
component: Category
},
{
path: '/category',
redirect: '/'
}
]
});
var vm = new Vue({
el: '#app',
router
});
</script>
别名
<div id="app">
<router-link :to="{ name: 'school', params: { id: 10, date: '0612'} }">学校信息</router-link>
<router-link to="/20/1234">学校信息2</router-link>
<router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
var School = {
template: `
<div>School 组件</div>
`
};
var router = new VueRouter({
routes: [
{
path: '/user/:id/info/school/:date',
name: 'school',
component: School,
alias: '/:id/:date'
}
]
});
var vm = new Vue({
el: '#app',
router
});
</script>
导航守卫
<div id="app">
<router-link to="/">首页</router-link>
<router-link to="/user">用户</router-link>
<router-link to="/category">分类</router-link>
<router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
var Index = {
template: `<div>这是首页功能</div>`
};
var User = {
template: `<div>这是用户功能</div>`
};
var Category = {
template: `<div>这是分类功能</div>`
};
var router = new VueRouter({
routes: [
{ path: '/', component: Index },
{ path: '/user', component: User },
{ path: '/category', component: Category },
]
});
router.beforeEach(function (to, from, next) {
if (to.path === '/user') {
next('/category');
} else {
next();
}
});
var vm = new Vue({
el: '#app',
router
})
</script>
Vue CLI
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,称为脚手架工具。
安装
? 安装 ? npm install –g @vue/cli ? 升级 ? npm update –g @vue/cli
项目搭建
创建项目: ? vue create project-demo 选择 Preset、包管理器 创建完成
运行项目: ? npm run serv
目录与文件
单文件组件可以将组件的功能统一保存在以 .vue 为扩展名的文 件中。
打包与部署
打包就是将 Vue CLI 项目编译为浏览器可识别的文件。 命令: ? npm run build
部署指的是将 Vue 项目dist 目录部署到服务器上。 安装静态文件服务器: ? npm install –g serve 在 dist 下通过 serve 命令部
|