基础内容
通过 data()
提供数据
vue中可以在 export default{}
里通过 data()
提供数据,data
必须是一个函数,return
一个对象
export default {
data () {
return {
uname: 'JuziYou',
age: 18
}
}
}
使用插值表达式显示数据
插值表达式使用两对大括号包裹,使用的数据需要在 data()
、methods
、computed
等地方存在,可以使用表达式,但是不能使用在标签属性
{{ uname }}
{{ obj.uname }}
{{ obj.age > 18 ? '成年' : '未成年' }}
v-bind
插值表达式不能使用在标签属性,需要使用 v-bind
需要设置动态html属性上,简写为 :
举例:
<a :href="url">戳戳</a>
<a v-bind:href="url">戳戳</a>
v-on
v-on
语法为 v-on:事件名='需要执行的代码/函数名/函数名(实参)'
需要在 methods
中提供事件处理函数,简写 @
举例:
<button @click='num = bum + 1'>Click</button>
<button @click='functionA'>Click</button>
<button @click='functionB('JuziYou')'>Click</button>
<button v-on:click='num = bum + 1'>Click</button>
<button v-on:click='functionA'>Click</button>
<button v-on:click='functionB('JuziYou')'>Click</button>
事件修饰符
.prevent
阻止默认行为.stop
阻止冒泡.once
程序运行期间只触发一次事件处理函数.native
在组件上调用事件
v-model
v-model
是一个语法糖 @input
和 :value
组合到了一起,它吧属性和数据双向绑定到一起。双向绑定即数据变化视图同步变化,视图变化数据同步变化。
语法:v-model="数据变量"
<button v-model="数据变量"> 戳戳 </button>
在父子组件通信时,如果 :value
传参给子组件 $emit('input', 值)
可以使用 v-model
代替
v-model
修饰符
.number
和 .parseFloat
转换为数字类型.trim
去除首尾空白(空格).lazy
使用 change
事件改变数据(默认为 imput
事件改变数据)
v-text
和 v-html
v-text
和 v-html
会更新DOM对象的innerText或者innerHTML,并且会覆盖差值表达式 v-text
不会识别HTML标签,v-html
会识别HTML标签
语法:
<p v-text="数据变量"></p>
<p v-html="数据变量"></p>
v-show
和 v-if
及 v-else
v-show
和 v-if
控制标签的显示或隐藏,true
或 false
v-show
使用CSS的 display:none
来隐藏v-if
将会直接从DOM树上移除
频繁切换显示的情况下使用 v-show
因为使用 display:none
来切换显示隐藏不会频繁创建元素节省性能,v-if
是惰性的在 false
时不会创建元素节省初期渲染开销
语法:
<p v-show="true"></p>
<p v-if="false"></p>
v-if
与 v-else
和 v-else-if
同时使用,方便通过变量控制一套标签出现或者隐藏
<template>
<div>
<h1 v-if="yukari>= 60">紫老ffhfhewufuiefefrwgfuktyr</h1>
<h1 v-else-if="yukari>= 30">紫妈</h1>
<h1 v-else>紫</h1>
</div>
</template>
<script>
export default {
data(){
return {
yukari: 16
}
}
}
</script>
v-for
v-for
常用于列表渲染,按照数据循环生成,可以遍历数组、对象、数字、可遍历解构的字符串
每一项唯一标识符作为 :key="索引"
,可以最大限度的复用你的DOM,:key="索引"
的索引只能是数字或者字符串
语法:v-for="(值, 索引) in 目标" :key="索引"
v-for="值 in 目标" :key="值下的可用于索引的值"
<template>
<div>
<ul>
<li v-for="(item,index) in list" :key="index">
{{ item }} > {{ index }}
</li>
</ul>
</div>
</template>
<script>
export default {
data(){
return {
list:['JuziYou','MikanpaperYuzu','橘纸柚']
}
}
}
</script>
<template>
<div>
<ul>
<li v-for="(value, key) in preson" :key="key">
{{ value }} · {{ key }}
</li>
</ul>
</div>
</template>
<script>
export default {
data(){
return {
preson:{
uname: '八云紫',
skill: '操纵界线的能力',
age: 18
}
}
}
}
</script>
<template>
<div>
<ul>
<li v-for="(item,index) in personList" :key="index">
>>>{{item.uname}}
<p>{{item.skill}}</p>
</li>
</ul>
</div>
</template>
<script>
export default {
data(){
return {
personList:[
{uname:'博丽灵梦',home:'博丽神社'},
{uname:'琪露诺',home:'雾之胡'},
{uname:'蕾米莉亚',home:'红魔馆'},
{uname:'帕秋莉',home:'红魔馆'}
]
}
}
}
</script>
<template>
<div>
<ul>
<li v-for="(item,i) in 5" :key="i">
{{item}} · {{i}}
</li>
</ul>
</div>
</template>
数组的数据更新监测
数组方法中能引起页面更新的方法有:push
、pop
、shift
、unshift
、splice
、sort
、reverse
其他无法引起页面更新的方法可以通过赋值来完成更新
通过下标来更新值不会触发页面更新需要使用 $set
来更新数组
语法:this.$ste(要改变的对象, 要改变的位置, 要改变的值)
<template>
<div>
<ul>
<li v-for="(item,index) in list" :key="index">{{item}}</li>
</ul>
<button @click="changeFn">changeFn</button>
</div>
</template>
<script>
export default {
data() {
return {
list: ['博丽灵梦', '琪露诺', '八云紫']
}
},
methods:
changeFn(){
this.$set(this.list, 1, "魔理沙")
}
}
}
</script>
动态绑定 class
使用 v-bind:class
设置动态属性一般使用简写 :class
允许使用对象或者数组:class
不会影响到原有的class属性
使用对象动态绑定 :class="{类名:布尔值}"
如果布尔值为 true
就有这个类名,false
则没有
使用数组动态绑定 :class="数组"
标签会有数组里面的所有类名
<template>
<div>
<div :class="str">Nya</div>
</div>
</template>
<script>
export default {
data(){
return {
str: 'green'
}
}
}
</script>
<template>
<div>
<div :class="isRed ? 'red' : ''"></div>
</div>
</template>
<script>
export default {
data(){
return {
isRed: true
}
}
}
</script>
<template>
<div>
<div :class="{yukari: isRed, suka: !isRed}"></div>
</div>
</template>
<script>
export default {
data(){
return {
isRed: true
}
}
}
</script>
<template>
<div>
<div :class="arr"></div>
</div>
</template>
<script>
export default {
data(){
return {
arr: ['show', 'mask', 'red', 'paper']
}
}
}
</script>
动态绑定 style
使用 v-bind:style
设置动态属性一般使用简写 :style
语法 :style="{样式名:样式值}"
样式名为CSS属性的驼峰命名法
<template>
<div>
<h1 :style="{ fontSize: '50px', color: fontColor}">黄色的</h1>
</div>
</template>
<script>
export default {
data(){
return{
fontColor: 'yellow'
}
}
}
</script>
computed
计算属性
计算属性必须在 computed
节点中,多用于多个数据影响一个数据的场景,根据现有的数据区计算出新的数据并且有缓存,在数据不发生变化的情况下只会执行一次,数据有变化时会重新计算并缓存,写法是一个函数,一定需要返回值是最终值
示例翻转字符串:
<template>
<div>
<h1>{{reverseStr}}</h1>
</div>
</template>
<script>
export default {
data(){
return{
uname: 'MikanpaperYuzu'
}
},
computed: {
reverseStr(){
return this.uname.split('').reverse().join('')
}
}
}
</script>
计算属性默认情况下只能获取不能修改,如果需要修改需要用到完整写法
完整写法示例:
<template>
<div>
<h1>计算属性的完整写法</h1>
<h1>{{fullName}}</h1>
<button @click="clickFn">点我</button>
</div>
</template>
<script>
export default {
data(){
return{
firstName:'Juzi',
lastName:'You'
}
},
computed: {
fullName: {
get(){
return this.firstName + '-' + this.lastName
},
set(val){
this.firstName = val.split('-')[0]
this.lastName = val.split('-')[1]
}
}
},
methods: {
clickFn(){
this.fullName = 'MikanPaper-Yuzu'
}
}
}
</script>
watch
属性监听
属性监听必须写在 watch
节点中,只要监听的属性值发生了变化就会执行,多用于一个属性影响多个属性的场景,没有缓存但是可以异步,简单写法无法监听复杂类型的写法,需要使用完整写法监听复杂数据类型
watch: {
监听的属性 (变化后的值, 变化前的值) {
}
}
示例:
<template>
<div>
<h2>{{ uname }}</h2>
<button @click="uname = 'MikanpaperYuzu'">给我变</button>
</div>
</template>
<script>
export default {
data(){
return{
uname: 'JuziYou'
}
},
watch:{
uname(newVal, oldVal){
console.log('魔法少女 ' + oldVal + ' 变 ' + newVal);
}
}
}
</script>
immediate: true
代表一进入页面立即执行deep: true
代表升读监听可以监听到复杂数据类型内部的变化handler(){}
每次变化时触发的函数watch: {
接听的属性:{
immediate: true, //代表一进入页面立即执行
deep: true, // 代表升读监听可以监听到复杂数据类型内部的变化
handler(){ // handler 是每次变化时触发的函数
}
}
}
示例:
<template>
<div>
<h2>{{ obj.uname }}</h2>
<button @click="mya">给我变</button>
</div>
</template>
<script>
export default {
data(){
return{
obj: {
uname : 'JuziYou'
}
}
},
watch: {
obj:{
immediate: true,
deep: true,
handler(){
console.log("变了喵");
}
}
},
methods: {
mya(){
this.obj.uname = "MikanpaperYuzu"
}
}
}
</script>
组件基础
引入组件
组件分为全局引入和局部引入,一般使用大驼峰命名法,除了驼峰, 如果使用小写还可以使用 -
转换链接不同的单词,如一个注册组件名为 <JuziYou />
可以直接使用转换连接 <juzi-you />
也能解析到父组件。如果标签没有内容可以直接使用自结束标签
局部引入
局部引入将组件注册在当前Vue文件,只可以用在这个Vue文件中。
使用 import 组件对象 from 'Vue文件路径'
引入组件
然后 components: { 组件名: 组件对象 }
注册组件
示例:
<template>
<div id="app">
<Pannel />
</div>
</template>
<script>
import PannelLoc from './components/Pannel.vue'
export default {
components: { Pannel: PannelLoc }
}
</script>
<template>
<div>
<h1>Nya</h1>
</div>
</template>
全局引入
全局引入在 main.js
引入组件并使用,注册在全局整个项目中都可以使用
使用 import 组件对象 from 'Vue文件路径'
引入组件
然后 Vue.component("组件名", 组件对象)
注册组件
示例:
import Vue from 'vue'
import App from './App.vue'
// 引入组件
import Pannel from "./components/Pannel";
// 全局注册
Vue.component('PannelGol', Pannel)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
<template>
<div>
<h1>Nya</h1>
</div>
</template>
<template>
<div>
<PannelGol></PannelGol>
</div>
</template>
组件样式 scoped
吧样式只应用于当前组件,给组件的 <style>
加上 scoped
会给这个组件的所有元素添加自定义属性,以及当前组件的CSS添加交集选择器,只有这个自定义属性的标签才能被样式选中
示例:
<template>
<div>
<h1>MikanpaperYuzu</h1>
<ChildOne />
</div>
</template>
<script>
import ChildOne from './components/ChildOne.vue'
export default {
components: {
ChildOne
}
}
</script>
<style>
</style>
<template>
<div>
<h1>JuziYou</h1>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
h1{
color: orange
}
</style>
组件 name
属性
一般使用一些框架会用到,以保证框架的命名风格所以懒得写太清楚(((
示例:
<template>
<div>
<JuziYou />
</div>
</template>
<script>
import ChildCom from './components/ChildCom.vue'
export default {
components:{
[ChildCom.name]: ChildCom
}
}
</script>
<template>
<div>
<p>JuziYou</p>
</div>
</template>
<script>
export default {
name:'JuziYou'
}
</script>
父向子通讯
在父组件的子组件标签上添加自定义属性,然后在子组件使用 props
接收
注: 子组件不能修改父组件传来的 props
示例:
<template>
<div>
<MyProduct title="勾勾果" price="200" intro="蒙德产勾勾果" />
<MyProduct title="甜甜花" price="100" intro="蒙德产甜甜花" />
</div>
</template>
<script>
// 定义局部变量
import MyProduct from './components/MyProduct.vue'
export default {
components: {
MyProduct,
}
}
</script>
<template>
<div>
<h3>标题: {{ title }}</h3>
<p>价格: {{ price }}元</p>
<p>{{ intro }}</p>
</div>
</template>
<script>
export default
props: ['title','price','intro']
}
</script>
子向父通讯
在父组件的标签上设置自定义事件组件 @事件名="方法名"
,然后在子组件中使用 this.$emit(事件名, 传给父元素的值)
触发自定义事件,$emit
第二个值之后为返回给父元素的值,在父亲元素接收的方法中对应形参
示例:
<template>
<div>
<MyProduct
:title="list.title"
:price="list.price"
:intro="list.intro"
@upMora="upFn"
/>
</div>
</template>
<script>
// 定义局部变量
import MyProduct from './components/MyProduct.vue'
export default {
components: {
MyProduct,
}
data() {
return {
list:{
title: '勾勾果'
price: '200'
intro: '蒙德产勾勾果'
}
}
},
methods: {
upFn(num){
this.list.price = num
}
}
}
</script>
<template>
<div>
<h3>标题: {{ title }}</h3>
<p>价格: {{ price }}元</p>
<p>{{ intro }}</p>
<button @click="$emit('upMora', 1000)">价格改为1000元</button>
</div>
</template>
<script>
export default
props: ['title','price','intro']
}
</script>
props
校验
校验父模块向子模块传来的数据是否符合需求
key
是接收值名称,value
是接收的类型export default {
props:{
user:String
}
}
value
设置为接收的类型数组export default {
props:{
age: [String, Number]
}
}
type
表示接收的类型,required: true
来打开必传export default {
props:{
gender:{
type: String,
required: true
}
}
}
type
表示接收的类型,default: 值
来设置默认值export default {
props:{
salary:{
type: String,
default: 'JuziYou'
}
}
}
type
表示接收的类型,使用 validator(传过来的值){}
它 return
出来的值 true
和 false
来校验通过或不通过,如果 return
了 false
将会在控制台打印错误export default {
props:{
// 检测传入 list 是否 length 大于 3
list: {
type: Array,
validator(val){
if(val.length >= 3){
return true
}
return false
}
}
}
}
.sync
修饰符
可以让繁琐的父子通讯变得简单在使用.sync
修饰符后在子组价使用 update:自定义变量 来更改父组件变量绑定的值就可以完成父子组件的通讯,相当于在父组件的标签上添加了@update:属性名=" 变量名 = $event"
,$event
是默认参数
<template>
<div>
<SyncUpdate :text.sync="name"/>
</div>
</template>
<script>
import SyncUpdate from '@/components/sync-update.vue'
export default {
components:{
SyncUpdate
},
data () {
return {
name: 'Mikanpapre'
}
}
}
</script>
<template>
<div>
<div>{{ text }}</div>
<!-- 使用 update:自定义变量 来更改父组件变量绑定的值 -->
<button @click="$emit('update:text', 'Nya')">戳戳</button>
</div>
</template>
<script>
export default {
props: ['text']
}
</script>
$parent
$parent
可以在子组件获取到父组件的实例
事件总线 EventBus
如果两个子组件通过父组件进行通讯会非常复杂,通过一个空的Vue对象当作事件总线常用于跨组件通讯的通用方案,在组件A使用 EventBus.$emit('事件名', 值)
触发事件,在组件B使用 EventBus.$on('事件名', 函数体)
监听事件
import Vue from 'vue'
引入Vue使用
export default new Vue()
对外暴露一个Vue实例import Vue from 'vue'
export default new Vue()
<template>
<div>我是A
<button @click='clickfn'>戳</button>
</div>
</template>
<script>
import EventBus from '../EventBus'
export default {
methods:{
clickfn(){
EventBus.$emit('mikan')
}
}
}
</script>
created()
在事件创建时就执行<template>
<div>我是B</div>
</template>
<script>
import EventBus from '../EventBus'
export default {
created(){
EventBus.$on('mikan', ()=>{
console.log('喵');
})
}
}
</script>
APP.vue
导入两个组件并使用<template>
<div>
<h1>EventBus</h1>
<ChildA/>
<ChildB/>
</div>
</template>
<script>
import ChildA from './components/ChildA.vue'
import ChildB from './components/ChildB.vue'
export default {
components: {
ChildA,
ChildB
}
}
</script>
ref
和 $refs
ref
和 $refs
通常用于获取元素DOM或组件示例,将会挂载到 $refs
的组件对象内
获取DOM
在需要获取的DOM元素上 ref="值"
然后在 $refs.值
使用
<template>
<div>
<div ref="juziyou">JuziYou</div>
<button @click="clickFn">Click</button>
</div>
</template>
<script>
export default {
methods:{
clickFn(){
console.log(this.$refs.juziyou)
}
}
}
</script>
获取组件实例
在需要获取的组件自定义标签上 ref="值"
然后在 $refs.值
使用
<template>
<div>
<ChildB ref="childRef"/>
<button @click="childRefFn">Click</button>
</div>
</template>
<script>
import ChildB from './components/ChildB.vue'
export default {
components:{
ChildB
},
methods:{
childRefFn(){
console.log(this.$refs.childRef.uname)
this.$refs.childRef.logName()
}
}
}
</script>
<template>
<div>
ChildB
</div>
</template>
<script>
export default {
data(){
return{
uname: 'JuziYou',
}
},
methods:{
logName(){
console.log(this.uname)
}
}
}
</script>
$nextTick
由于Vue更新DOM是异步的,会导致需要在DOM更新之后的代码会被先执行,所以需要使用 $nextTick
$nextTick
接收一个函数作为参数,接收的函数将会在DOM更新后执行
如在点击按钮后显示输入框然后获取输入框的DOM:
<template>
<div>
<input type="text" ref="ipt" v-if="isShowInput">
<button @click="fn" v-else>Click</button>
</div>
</template>
<script>
export default {
data () {
return {
isShowInput: false
}
},
methods: {
fn () {
this.isShowInput = true
this.$nextTick(()=>{
console.log(this.$refs.ipt);
})
}
}
}
</script>
component
动态渲染组件
component
是Vue内置的一个组件用于动态的渲染组件,:is="值"
的值是什么就会渲染哪个子组件
<template>
<div>
<button @click="comName = 'ChildA'">ChildA</button>
<button @click="comName = 'ChildB'">ChildB</button>
<component :is="comName"></component>
</div>
</template>
<script>
import ChildA from './components/ChildA.vue'
import ChildB from './components/ChildB.vue'
export default {
components:{
ChildA,
ChildB
},
data(){
return{
comName: 'ChildA'
}
}
}
</script>
<template>
<div>
<h1>ChildA</h1>
</div>
</template>
<template>
<div>
<h1>ChildB</h1>
</div>
</template>
自定义指令
自定义指令分为全局和局部注册,在标签上 v-自定义指令名
进行使用
常用的:inserted
方法绑定此指令的元素插入到DOM时执行
语法为 inserted(形参){}
inserted(形参){}
第一个形参是绑定此指令的元素,第二个形参为当前自定义指令传入的值
update
方法绑定此指令的元素值发生变化时执行
语法为 update(形参){}
update(形参){}
第一个形参是绑定此指令的元素,第二个形参为当前自定义指令传入的值
main.js
内添加 Vue.directive
进行全局注册语法为
Vue.directive('指令名',{方法})
示例:在input标签创建时自动落焦
Vue.directive('focusglo', {
inserted(el){
el.focus()
}
})
export default
内使用 directives{对象}
进行局部注册,注册的自定义指令只能在当前组件使用示例:如 color
的值发生变化时重新设置使用了此自定义指令的元素的颜色
export default {
data () {
return {
color: 'orange'
}
}
directives: {
zy:{
inserted(el,binding){
el.style.color = binding.value
},
update(el,binding){
el.style.color = binding.value
}
}
}
}
插槽
插槽插在父组件的两个起始标签和结束标签之间,默认会放到默认 <slot>
插槽内<template>
中使用指令 v-slot:插槽名
来使用指定的插槽,也可以用 #插槽名来简写
,在子组件内的 <slot>
通过 name="插槽名"
变量的方式来设置插槽名
默认插槽可以使用 <template v-slot="变量名"></template >"
来接收传过来的参数,具名插槽可以之间加上等号变量名来接收传过来的的参数 <template v-slot:插槽名="变量名"></template >"
,在子组件内的 <slot>
通过添加自定义变量名的方式来传参
<template>
<div>
<!-- 使用組件時在父組件的兩個標簽之間插入 -->
<MyDialog>
<img src="https://lovemen.cc/usr/hotlink-ok/avatar.jpg" alt="">
</MyDialog>
<MyDialog>
<!-- <template v-slot:footer> 指定插入footer插槽 v-slot:插槽name -->
<!-- 在具名插槽下直接加上等號就可以接收,可以在等號内直接解構賦值 -->
<template v-slot:footer="{yes:okay,no}">
<button>{{ okay }}</button>
<button>{{ no }}</button>
</template>
<!-- 可以使用#簡寫 -->
<template #header>
<h3>溫馨提示</h3>
</template>
<!-- 默認插槽透過v-slot="變量名"接收傳過來的,將以對象形式呈現,只能在template内使用 -->
<template v-slot="obj">
{{obj}}
<p>你好,買?</p>
</template>
</MyDialog>
</div>
</template>
<script>
import MyDialog from './components/MyDialog.vue'
export default {
components:{
MyDialog
}
}
</script>
<template>
<div class="my-dialog">
<div class="header">
<slot name="header"></slot>
</div>
<div class="content">
<!-- slot表示此處有一個插槽 -->
<!-- 作用域插槽:通過插槽設置自定義參數傳數據 -->
<slot uname="MikanpapreYuzu" age="18"></slot>
</div>
<div class="footer">
<!-- name給插槽起名 -->
<slot name="footer" yes="好捏" no="打咩"></slot>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="less" scoped>
.my-dialog {
width: 400px;
padding: 10px 20px;
border: 3px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
路由
npm默认获取的 vue-router
版本为4,在Vue2中需要 vue-router
版本为3时才可以使用,所以在Vue2中需要 @3
指定 vue-router
安装版本
npm i [email protected]
路由就是路径和组件间的关系,创建路由的方式有在 main.js
创建路由和创建 router
文件夹在 index.js
中创建路由
在 main.js
创建路由
先在 main.js
内使用 import VueRouter from 'vue-router'
引入 vue-router
,然后使用 Vue.use(VueRouter)
让Vue使用 vue-router
插件 const router = new VueRouter(对象)
创建一个路由实例,在对象内添加一个 routes
数组,这个数组内每个对象都是一个匹配规则,import RouterPage from '@/views/RouterPage'
引入组件,router内的对象 path
为设置路由的路径 component
为设置路由指向的组件,最后在 new Vue
内添加const出来的变量名关联到Vue实例,匹配到的组件会在 <router-view></router-view>
渲染
import Vue from 'vue'
import App from './App.vue'
import My from '@/views/My'
import Part from '@/views/Part'
// 5 引入组件
import RouterPage from '@/views/RouterPage'
// 1引入vue-router
import VueRouter from 'vue-router'
// 2让Vue使用vue-router插件
Vue.use(VueRouter)
// 3创建路由实例
const router = new VueRouter({
// 6 routes 是一个数组,此数组里面的每一个对象都是一个匹配规则
routes:[
{
// 7设置路由路径
path:'/RouterPage',
// 8 给路径指向组件
component: RouterPage
}
]
})
Vue.config.productionTip = false
//4 吧路由实例关联router到vue实例
new Vue({
router,
render: h => h(App),
}).$mount('#app')
<template>
<div>
<h1>RouterPage</h1>
</div>
</template>
<template>
<div>
<a href="#/RouterPage"></a>
<div>
<router-view></router-view>
</div>
</div>
</template>
在 router
文件夹中的 index.js
创建路由
在 main.js
中创建路由不太好,应该每个模块干每个模块的事情
在 src
中创建 router
文件夹然后在文件夹中创建 index.js
,首先在 index.js
中使用 import Vue from 'vue'
引入Vue,然后使用 import VueRouter from 'vue-router'
引入 vue-router
,接着使用 Vue.use(VueRouter)
让Vue使用 vue-router
插件,使用 const router = new VueRouter(对象)
创建一个路由实例,在对象内添加一个 routes
数组,这个数组内每个对象都是一个匹配规则,import RouterPage from '@/views/RouterPage'
引入组件,router内的对象 path
为设置路由的路径 component
为设置路由指向的组件,export default router
让 index.js
对外暴露 router
实例,最后在 main.js
中使用 import router from '@/router/index.js'
引入路由实例再在 new Vue
中关联引入的实例 router
到Vue实例,匹配到的组件会在 <router-view></router-view>
渲染
// 1 引入Vue
import Vue from 'vue'
// 5 引入组件
import RouterPage from '@/views/RouterPage'
// 2 引入vue-router
import VueRouter from 'vue-router'
// 3 让Vue使用vue-router插件
Vue.use(VueRouter)
// 4 创建路由实例
const router = new VueRouter({
// 6 routes 是一个数组,此数组里面的每一个对象都是一个匹配规则
routes:[
{
// 7设置路由路径
path:'/RouterPage',
// 8 给路径指向组件
component: RouterPage,
}
]
})
// 对外暴露路由实例对象
export default router
import Vue from 'vue'
import App from './App.vue'
// 引入路由实例
import router from '@/router/index.js'
Vue.config.productionTip = false
//4 吧路由实例关联router到vue实例
new Vue({
router,
render: h => h(App),
}).$mount('#app')
<template>
<div>
<h1>RouterPage</h1>
</div>
</template>
<template>
<div>
<a href="#/RouterPage"></a>
<div>
<router-view></router-view>
</div>
</div>
</template>
查询字符串传参
在 to="path"
的path后面加 ?
查询字符串的方式传参,然后在组件内使用 $route.query
接收参数会以一个对象的形式接收
比如 <router-link to="/part?uname=JuziYou&ocname=MikanpaperYuzi">橘纸柚</router-link>
,在组件内 $route.query
将会收到一个对象 {uname:'JuziYou', ocname'MikanpaperYuzi'}
动态路由传参
首先在对应的路径复制一份然后在path中的路由加上 /:参数名
,然后在组件内使用 $route.params
接收参数会以一个对象的形式接收
比如:
一个路由为 /user
需要接收一个参数名为 uname
(.....省略后面或者前面代码)
..... = new VueRouter({
routes:[
.....
.....
{
path:'/user',
redirect: 'User'
},
{
path:'/user/:uname',
redirect: 'User'
},
.....
然后访问比如 localhost:8080/#/user/juziyou
,在组件内使用 $route.params
将会获取到一个对象 {uname:'juziyou'}
路由重定向以及默认页(404)
在路由实例的 routes
中起始位子添加一个匹配规则,匹配规则中 redirect
为重定向的路径
如从 /
重定向到 /juziyou
(.....省略后面或者前面代码)
..... = new VueRouter({
routes:[
{
path:'/',
redirect: '/juziyou'
},
.....
默认页则在路由实例的 routes
中的末尾添加一个 path
为通配符 *
的一个规则
如前面一个规则也没匹配上返回一个 NotFund
页面(.....省略后面或者前面代码)
..... = new VueRouter({
routes:[
.....
.....
{
path:'*',
redirect: 'NotFund'
},
.....
mode 与 base
mode
写在路由的实例中有个常用的参数 hash
和 history
,hash
会在URL中添加#号,history
则不会但是需要后端配合因为会向服务器发送真实路径。
以及可以通过 base
设置基础地址,比如要访问 /user
页面在 hash
模式下是 /#/user
如果在 history
模式下设置了 base
为 /juzi/
地址就是 /juzi/user
如修改 mode
到 history
(.....省略后面或者前面代码)
..... = new VueRouter({
mode: 'history',
base: '/juzi/'
.....
router-link
声明式导航
声明式导航 router-link
是 vue-router
提供的一个全局组件,使用 to="path"
来跳转路由路径
会给选中的路由自动的加上class类名,其分为模糊匹配类名和精确匹配类名,可以在路由实例内通过 linkActiveClas
修改模糊匹配类名以及通过 linkExactActiveClass
修改精确匹配类名
如通过 router-link
转到path /routerpage
<router-link to="/routerpage"></router-link>
如需要修改精确匹配类名为:juzi,模糊匹配类名为:you在路由实例内设置的方式(.....省略后面或者前面代码)
...... = new VueRouter({
linkActiveClass:'you',
linkExactActiveClass:'juzi',
......
编程式传参
通过调用函数的方式使用方法 $router.push
,使用 path
无法使用 params
传参所以推荐使用 name
来进行跳转
name
在路由配置中添加 name
属性,在编程式导航中如果需要使用 params
就得用 name
来跳转
全局守卫
所有的路由一旦匹配到规则在真正渲染解析前都会经过全局守卫,只有在全局守卫放行后才能真正渲染页面
在创建实例前先声明一个白名单变量或常量,吧路由(path)以字符串的形式储存在数组中,然后使用router.beforeEach(回调函数)
创建路由守卫,在路由解析访问之前都会经过回调函数,回调函数中有三个形参from
从哪里来的路由信息对象、to
要到那里去的路由信息对象、next
是否放行这是一个方法,如果next()
表示放行去的页面、next(路径)
则表示拦截到的页面,使用whiteList.includes
来匹配是否处于白名单
如验证用户是否登录
// 设置白名单
const whiteList = ['/login', '/regisrer']
router.beforeEach((to, from, next) => {
// 如果有token就放行
if (this.token) {
next()
} else {
// 如果没有token检查是不是去白名单页面
if (whiteList.includes(to.path)) {
// 如果是去白名单直接放行
next()
} else {
// 如果不是去白名单跳转到登录
next('/login')
}
}
})
生命周期
生命周期是Vue组件创建到销毁的过程
在特定的时间点执行特定的操作
分四大阶段,八个方法
官方文档
初始化
beforeCreate
在组件创建之前会被调用,此状态下无法获取自定义的数据,比如 data
中的数据created
会在初始化数据并当前实例代理了数据后执行,一般会在此生命周期钩子中请求服务器数据
挂载
beforeMount
无法获取到DOM元素因为这个时候还是虚拟DOMmounted
中就可以获取到真实DOM了
更新
beforeUpdate
在页面使用中的数据发生变时虚拟DOM更新之前运行updated
在使用中的数据发生变化时虚拟DOM更新到页面后运行
销毁
beforeDestroy
在销毁前运行,一般用来解绑一些事件,比如说定时器destroyed
咋子销毁后运行
keep-alive
缓存
<keep-alive>
是Vue内置的全局组件可以吧组件缓存到内存中,使用<keep-alive>
被缓存的组件有两个生命周期activated
组件被激活deactivated
组件被隐藏
vuex
vuex是vue的一个状态(数据)管理工具(也是插件),方便的解决多组件的共享状态,拥有响应式、操作简洁的优势
一般情况下多组件的数据共享会存在vuex中
创建仓库
一般为了维护项目的目录整洁会在src
目录下新建store
目录放置index.js
首先在创建Vuex实例然后再在main.js
中导入挂载到Vue实例上Vuex.Store()
括号内是一个对象
// 引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 注册vuex插件
Vue.use(Vuex)
// 创建仓库实例
const store = new Vuex.Store()
// 导出仓库
export default store
import Vue from 'vue'
import App from './App.vue'
// 引入store
import store from '@/store'
Vue.config.productionTip = false
new Vue({
// 挂载到 Vue 实例
store,
render: h => h(App)
}).$mount('#app')
state
state提供唯一的公共数据源,所有的共享数据需要放到state中储存,可以在任何组件中使用$store.state.键
来获取state中的数据也可以通过mapState()
映射到computed
中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// 设置 State
state:{
uname: 'JuziYou',
age: 18
}
})
export default store
<template>
<div>
<!-- 直接使用 $store.state.uname 获取 uname 的值 -->
<p>{{ $store.state.uname }}</p>
<!-- 直接使用映射计算属性得到的值 -->
<p>{{ age }}</p>
</div>
</template>
<script>
// 引入 mapState
import { mapState } from 'vuex'
export default {
computed:{
// mapState() 得到的是一个数组中对应的对象可以使用 ... 展开运算符展开到计算属性中
...mapState(['age'])
}
}
</script>
mutation
state中的数据只能通过mutation修改,用于父组件需要修改仓库中的数据
在vuex实例中定义mutation
,它是一个对象里面存储修改state的方法,每个方法的第一个形参是当前仓库的state,第二个是传入的参数
可以通过$store.commit('方法', 传参)
来调用mutation中的方法,传参只能传一个参数如果需要传多个使用复杂数据类型来完成,比如说对象
还可以通过辅助函数mapMutations(数组)
的方式使用展开运算符映射到methods
中,需要使用this.方法
来调用,使用起来和mapState()
很像
actions
actions负责仓库内的异步操作,mutation只能用于同步更新数据
在vuex实例中定义actions
,它是一个对象里面存储异步的方法,每个方法的第一个形参拥有仓库实例的所有属性和方法,第二个是传入的参数传参只能传一个参数如果需要传多个使用复杂数据类型来完成,比如说对象
可以通过$store.dispatch('方法', 传参)
来调用
也可以通过辅助函数mapActions(数组)
来调用使用展开运算符映射到methods
getters
getters使用仓库state中现有的数据计算出新的数据
在vuex实例中定义getters
,每个方法的第一个形参是当前仓库的state,必须要有返回值
可以通过$store.getters.方法
来调用
也可以通过辅助函数mapGetters(数组)
的方式使用展开运算符映射到computed
中
module 模块
如果使用单一的index.js
项目大后应用会变得非常复杂相对臃肿
在store
文件夹中创建一个用于存放模块的文件夹,export default
向外暴露键state
、mutations
、actions
、getters
值就是它们所需要的值,访问模块中的数据可以直接通过$store.state.模块名.数据键
来访问mutations
、actions
、getters
默认情况下全局可以调用,然后在
index.js中引入模块并在
modules中注册,组件的
state以对象的形式挂载到
state`下
export default {
state: {},
mutations: {},
actions: {},
getters: {}
}
import Vue from 'vue'
import Vuex from 'vuex'
// 引入子模块
import data from '@/store/data'
Vue.use(Vuex)
const store = new Vuex.Store({
// 使用modules来引入子模块
// 会将挂载组件的state以对象的形式挂载到state下
modules:{
data
},
})
namespaced 命名空间
开启命名空间后子模块的mutations、actions、getters就不会注册在仓库全局,在子模块的export default
中添加namespaced: true
,开启后$store
访问模块内的方法需要模块名/函数名
辅助函数需要在数组前增加模块名如mapState(模块名, 数组)
,然后通过this.方法
来调用
辅助函数还可以通过加/
的方式来使用(如mapState(['模块名/方法名']
),在调用方法时得this[模块名/方法名]()
来调用
export default {
namespaced: true,
}
createNamespacedHelpers
createNamespacedHelpers
辅助函数会返回一个对象里有mapActions
、mapGetters
、mapMutations
、mapState
通过解构赋值和重命名的方式来提取映射
export default {
namespaced: true,
state: {
uname: 'JuziYou'
},
mutations: {
updateName (state, payload) {
state.uname = payload
}
}
}
import Vue from 'vue'
import Vuex from 'vuex'
import datas from '@/store/modules/datas'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
getters: {
},
modules: {
datas
}
})
export default store
<template>
<div>
<div>{{ $store.state.datas.uname }}</div>
<button @click="updateUname">Mikanpapre</button>
</div>
</template>
<script>
import { createNamespacedHelpers } from 'vuex'
const { mapMutations: userMapMutations } = createNamespacedHelpers('datas')
export default {
methods: {
...userMapMutations(['updateName']),
updateUname () {
this.updateName('Mikanpapre')
}
}
}
博客环境损坏新增评论暂不可用