(三)Vue使用

概述

基本使用,组件使用—常用,必须会
高级特性—不常用,但体现深度
Vuex和Vue-router的使用

面试题

v-show和v-if的区别
为何v-for中要用key
描述Vue组件生命周期(有父子组件的情况)
Vue组件如何通讯
描述组件渲染和更新的过程
双向数据绑定v-model的实现原理

Vue基本使用

日常使用,必须掌握,面试必考(不一定会考)
梳理知识点,从冗长的文档中摘出考点和重点
考察形式不限(参考后面的面试真题),但都在范围之内

模板(指令、插值)

插值、表达式
指令、动态属性
v-html:会有XSS风险,会覆盖子组件

<template>
    <div>
        <p>文本插值 {{message}}</p>
        <p>JS 表达式 {{ flag ? 'yes' : 'no' }} (只能是表达式,不能是 js 语句)</p>

        <p :id="dynamicId">动态属性 id</p>

        <hr/>
        <p v-html="rawHtml">
            <span>有 xss 风险</span>
            <span>【注意】使用 v-html 之后,将会覆盖子元素</span>
        </p>
        <!-- 其他常用指令后面讲 -->
    </div>
</template>

<script>
export default {
    data() {
        return {
            message: 'hello vue',
            flag: true,
            rawHtml: '指令 - 原始 html <b>加粗</b> <i>斜体</i>',
            dynamicId: `id-${Date.now()}`
        }
    }
}
</script>

computed和watch

computed有缓存,data不变则不会重新计算
watch如何深度监听
watch监听引用类型,拿不到oldVal

<template>
    <div>
        <p>num {{num}}</p>
        <p>double1 {{double1}}</p>
        <input v-model="double2"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            num: 20
        }
    },
    computed: {
        double1() {
            return this.num * 2
        },
        double2: {
            get() {
                return this.num * 2
            },
            set(val) {
                this.num = val/2
            }
        }
    }
}
</script>
<template>
    <div>
        <input v-model="name"/>
        <input v-model="info.city"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: '双越',
            info: {
                city: '北京'
            }
        }
    },
    watch: {
        name(oldVal, val) {
            // eslint-disable-next-line
            console.log('watch name', oldVal, val) // 值类型,可正常拿到 oldVal 和 val
        },
        info: {
            handler(oldVal, val) {
                // eslint-disable-next-line
                console.log('watch info', oldVal, val) // 引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
            },
            deep: true // 深度监听
        }
    }
}
</script>

class和style

使用动态属性
使用驼峰式写法

<template>
    <div>
        <p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
        <p :class="[black, yellow]">使用 class (数组)</p>
        <p :style="styleData">使用 style</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            isBlack: true,
            isYellow: true,

            black: 'black',
            yellow: 'yellow',

            styleData: {
                fontSize: '40px', // 转换为驼峰式
                color: 'red',
                backgroundColor: '#ccc' // 转换为驼峰式
            }
        }
    }
}
</script>

<style scoped>
    .black {
        background-color: #999;
    }
    .yellow {
        color: yellow;
    }
</style>

条件渲染

v-if v-else的用法,可使用变量,也可以使用===表达式
v-if和v-show的区别
v-if和v-show的使用场景:切换频繁使用v-show

v-show和v-if都能控制元素的显示和隐藏。
v-show本质就是通过设置css中的display设置为none,控制隐藏,无论true或者false初始都会进行渲染,因此切换开销比较小,初始开销较大
v-if是动态的向DOM树内添加或者删除DOM元素,因为懒加载,初始为false时,不会渲染,因此初始渲染开销较小,切换开销比较大,要不停的销毁和创建)
切换频繁使用v-show

<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>

<script>
export default {
    data() {
        return {
            type: 'a'
        }
    }
}
</script>

循环(列表)渲染

如何遍历对象?—也可以用v-for
key的重要性。key不能乱写(如random或者index)
v-for和v-if不能一起使用

因为v-for的优先级比v-if高,意味着v-if 将分别重复运行于每个 v-for 循环中,造成不必要的计算,影响性能
解决方法:将 v-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>

<script>
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' },
            }
        }
    }
}
</script>

事件

event参数,自定义参数
事件修饰符,按键修饰符
【观察】事件被绑定到哪里

<template>
    <div>
        <p>{{num}}</p>
        <button @click="increment1">+1</button>
        <button @click="increment2(2, $event)">+2</button>
    </div>
</template>

<script>
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)
    }
}
</script>

在这里插入图片描述
在这里插入图片描述

表单

v-model
常见表单项textarea checkbox radio select
修饰符lazy number trim

当添加.lazy修饰符之后,相当于 双向数据绑定不起作用了,主要用于控制数据同步的时机,改变input框中的内容并不会使数据发生变化,当输入框失去焦点后触发change事件,数据才更新

<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>

<script>
export default {
    data() {
        return {
            name: '双越',
            age: 18,
            desc: '自我介绍',

            checked: true,
            checkedNames: [],

            gender: 'male',

            selected: '',
            selectedList: []
        }
    }
}
</script>

组件

props和$emit

组件间通讯-自定义事件

//index.vue
<template>
    <div>
        <Input @add="addHandler"/>
        <List :list="list" @delete="deleteHandler"/>
    </div>
</template>

<script>
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() {
        // eslint-disable-next-line
        console.log('index created')
    },
    mounted() {
        // eslint-disable-next-line
        console.log('index mounted')
    },
    beforeUpdate() {
        // eslint-disable-next-line
        console.log('index before update')
    },
    updated() {
        // eslint-disable-next-line
        console.log('index updated')
    },
}
</script>
//Input.vue
<template>
    <div>
        <input type="text" v-model="title"/>
        <button @click="addTitle">add</button>
    </div>
</template>

<script>
import event from './event'

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

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

            this.title = ''
        }
    }
}
</script>
//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>

<script>
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) {
            // eslint-disable-next-line
            console.log('on add title', title)
        }
    },
    created() {
        // eslint-disable-next-line
        console.log('list created')
    },
    mounted() {
        // eslint-disable-next-line
        console.log('list mounted')

        // 绑定自定义事件
        event.$on('onAddTitle', this.addTitleHandler)
    },
    beforeUpdate() {
        // eslint-disable-next-line
        console.log('list before update')
    },
    updated() {
        // eslint-disable-next-line
        console.log('list updated')
    },
    beforeDestroy() {
        // 及时销毁,否则可能造成内存泄露
        event.$off('onAddTitle', this.addTitleHandler)
    }
}
</script>

生命周期

单个组件
  • 挂载阶段(beforeCreate、created、beforeMount、mounted)
  • 更新阶段(beforeUpdate、updated)
  • 销毁阶段(beforeDestory、destroyed )

在这里插入图片描述
created和mounted区别
created把vue示例给初始化,只是存在js内存模型的内存变量而已,并没有开始渲染;
mounted组件真正在网页上汇聚完成了,页面渲染完成了

beforeDestory上可以做什么
解除绑定,销毁子组件以及事件监听器

父子组件

在这里插入图片描述
在这里插入图片描述
创建初始化vue实例是从外到内,只有父组件初始化完才能初始化子组件
渲染是从内到外,只有把子组件渲染完父组件才能渲染完
beforeUpdate:更新的时候父组件的data首先被修改,首先执行beforeUpdate
updated:只有子组件更新完了父组件才能更新完

渲染过程:父组件挂载完成一定是等子组件都挂载完成后,才算是父组件挂载完,所以父组件的mounted在子组件mouted之后。父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

子组件更新过程:
影响到父组件: 父beforeUpdate -> 子beforeUpdate->子updated -> 父updated
不影响父组件: 子beforeUpdate -> 子updated

父组件更新过程:
影响到子组件: 父beforeUpdate -> 子beforeUpdate->子updated -> 父updated
不影响子组件: 父beforeUpdate -> 父updated

销毁过程:父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

不管是哪种情况,都一定是父组件等待子组件完成后,才会执行自己对应完成的钩子

高级特性

//index.vue
<template>
    <div>
        <p>vue 高级特性</p>
        <hr>

        <!-- 自定义 v-model -->
        <!-- <p>{{name}}</p>
        <CustomVModel v-model="name"/> -->

        <!-- nextTick -->
        <!-- <NextTick/> -->

        <!-- slot -->
        <!-- <SlotDemo :url="website.url">
            {{website.title}}
        </SlotDemo> -->
        <!-- <ScopedSlotDemo :url="website.url">
            <template v-slot="slotProps">
                {{slotProps.slotData.title}}
            </template>
        </ScopedSlotDemo> -->

        <!-- 动态组件 -->
        <!-- <component :is="NextTickName"/> -->
        
        <!-- 异步组件 -->
        <!-- <FormDemo v-if="showFormDemo"/>
        <button @click="showFormDemo = true">show form demo</button> -->

        <!-- keep-alive -->
        <!-- <KeepAlive/> -->

        <!-- mixin -->
        <MixinDemo/>
    </div>
</template>

<script>
// import CustomVModel from './CustomVModel'
// import NextTick from './NextTick'
// import SlotDemo from './SlotDemo'
// import ScopedSlotDemo from './ScopedSlotDemo'
// import KeepAlive from './KeepAlive'
import MixinDemo from './MixinDemo'

export default {
    components: {
        // CustomVModel
        // NextTick
        // SlotDemo,
        // ScopedSlotDemo,
        // FormDemo: () => import('../BaseUse/FormDemo'),
        // KeepAlive
        MixinDemo
    },
    data() {
        return {
            name: '双越',
            website: {
                url: 'http://imooc.com/',
                title: 'imooc',
                subTitle: '程序员的梦工厂'
            },
            // NextTickName: "NextTick",
            showFormDemo: false
        }
    }
}
</script>

自定义v-model

//index.vue
<template>
    <div>
        <!-- 自定义 v-model -->
        <p>{{name}}</p>
        <CustomVModel v-model="name"/>
    </div>
</template>

<script>
import CustomVModel from './CustomVModel'

export default {
    components: {
        CustomVModel
    },
    data() {
        return {
            name: '双越',
        }
    }
}
</script>
//CustomVModel.vue
<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>

<script>
export default {
    model: {
        prop: 'text1', // 对应 props text1
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}
</script>

refs与$nextTick

Vue是异步渲染(原理部分会详细讲解)
data改变之后,DOM不会立刻渲染
$nextTick会在DOM渲染之后被处罚,以获取最新DOM节点

//index.vue
<template>
    <div>
        <!-- nextTick -->
        <NextTick/>
    </div>
</template>

<script>
import NextTick from './NextTick'

export default {
    components: {
        NextTick
    },
    data() {
        return {
        }
    }
}
</script>
//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>

<script>
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 ) //没有$nextTick返回3,6,有返回6,9
        })
    }
  }
}
</script>

slot

基本使用
//index.vue
<template>
    <div>
 		<!-- slot -->
        <SlotDemo :url="website.url">
            {{website.title}}
        </SlotDemo>
    </div>
</template>

<script>
import SlotDemo from './SlotDemo'

export default {
    components: {
        SlotDemo
    },
    data() {
        return {
             website: {
                url: 'http://imooc.com/',
                title: 'imooc',
                subTitle: '程序员的梦工厂'
            },
        }
    }
}
</script>
//SlotDemo.vue
<template>
    <a :href="url">
        <slot>
            默认内容,即父组件没设置内容时,这里显示
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
    data() {
        return {}
    }
}
</script>
作用域插槽
//index.vue
<template>
    <div>
    	<ScopedSlotDemo :url="website.url">
            <template v-slot="slotProps">
                {{slotProps.slotData.title}}
            </template>
        </ScopedSlotDemo>
    </div>
</template>

<script>
import ScopedSlotDemo from './ScopedSlotDemo'

export default {
    components: {
        ScopedSlotDemo
    },
    data() {
        return {
             website: {
                url: 'http://imooc.com/',
                title: 'imooc',
                subTitle: '程序员的梦工厂'
            },
        }
    }
}
</script>
//ScopedSlotDemo.vue
<template>
    <a :href="url">
        <slot :slotData="website">
            {{website.subTitle}} <!-- 默认值显示 subTitle ,即父组件不传内容时 -->
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
    data() {
        return {
            website: {
                url: 'http://wangEditor.com/',
                title: 'wangEditor',
                subTitle: '轻量级富文本编辑器'
            }
        }
    }
}
</script>
具名插槽

在这里插入图片描述

动态组件

:is="component-name"用法
需要根据数据,动态渲染的场景,即组件类型不确定
在这里插入图片描述
比如一个新闻详情页,可能包含text、image、video组件,而且排序展示可能不一致

//index.vue
<template>
    <div>
   <!-- 动态组件 -->
       <!-- <component :is="NextTickName"/> -->
       <div v-for="(val,key) in newsData" :key="key">
			<component :is="val.tye"/>
	   </div>
    </div>
</template>

<script>
import ScopedSlotDemo from './ScopedSlotDemo'

export default {
    components: {
        ScopedSlotDemo
    },
    data() {
        return {
            //NextTickName: "NextTick",
            newsData:[
				1:{type:'text},
				2:{type:'text},
				3:{type:'image},
			]
        }
    }
}
</script>

异步组件

import()函数
按需加载,异步加载大组件

//index.vue
<template>
    <div>
  		<!-- 异步组件 -->
        <FormDemo v-if="showFormDemo"/>
        <button @click="showFormDemo = true">show form demo</button>
    </div>
</template>

<script>

export default {
    components: {
        FormDemo: () => import('../BaseUse/FormDemo')
    },
    data() {
        return {
             showFormDemo: false
        }
    }
}
</script>

keep-alive

缓存组件
频繁切换,不需要重复渲染
Vue常见性能优化

//index.vue
<template>
    <div>
  		<!-- keep-alive -->
        <KeepAlive/>
    </div>
</template>

<script>
import KeepAlive from './KeepAlive'
export default {
    components: {
       KeepAlive
    },
    data() {
        return {
             showFormDemo: false
        }
    }
}
</script>
//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>

<script>
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
        }
    }
}
</script>
//KeepAliveStateA.vue
<template>
    <p>state A</p>
</template>

<script>
export default {
    mounted() {
        // eslint-disable-next-line
        console.log('A mounted')
    },
    destroyed() {
        // eslint-disable-next-line
        console.log('A destroyed')
    }
}
</script>
//KeepAliveStateB.vue
<template>
    <p>state B</p>
</template>

<script>
export default {
    mounted() {
        // eslint-disable-next-line
        console.log('B mounted')
    },
    destroyed() {
        // eslint-disable-next-line
        console.log('B destroyed')
    }
}
</script>
//KeepAliveStateC.vue
<template>
    <p>state C</p>
</template>

<script>
export default {
    mounted() {
        // eslint-disable-next-line
        console.log('C mounted')
    },
    destroyed() {
        // eslint-disable-next-line
        console.log('C destroyed')
    }
}
</script>

点击A-B-C-A-B-C
未加keep-alive前
在这里插入图片描述
加keep-alive后,离开不会destroyed,再次加载不会mounted
在这里插入图片描述

mixin

多个组件有相同的逻辑,抽离出来
mixin并不是完美的解决方案,会有一些问题
Vue 3 提出的Composition API旨在解决这些问题

//index.vue
<template>
    <div>
  		<!-- mixin -->
        <MixinDemo/>
    </div>
</template>

<script>
import MixinDemo from './MixinDemo'
export default {
    components: {
       MixinDemo 
    },
    data() {
        return {
        }
    }
}
</script>
//MixinDemo.vue 
<template>
    <div>
        <p>{{name}} {{major}} {{city}}</p>
        <button @click="showName">显示姓名</button>
    </div>
</template>

<script>
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)
    }
}
</script>
//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)
    }
}
mixin问题

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

Vuex使用

面试考点并不多(因为熟悉Vue之后,vuex没有难度)
但基本概念,基本使用和API必须掌握
可能会考察state的数据结构设计(后面会讲)

Vuex基本概念

state
getters
action
mutation
异步操作在Actions里进行

用于Vue组件

dispatch
commit
mapState
mapGetters
mapActions
mapMutations

Vuex 是专门为 Vue.js 设计的状态管理库,简单地说就是采用全局单例模式,将组件的共享状态抽离出来管理,使组件树中的每一个位置都可以获取共享的状态(变量)或者触发行为。实现响应式的全局变量

state–状态,在store实例中注册state;在组件中使用store.state访问

getters–类似计算属性,对store中某个属性相同的处理操作抽出出来,做了一个公共的处理,组件中通过store.getters调用

action–异步更改状态,参数有context和payload,context.state获取store变量,context.commit触发mutation,提交mutation去修改state,组件中使用this.store.dispatch调用

mutation–更改store中状态的唯一方法,参数有state和payload,不能包含异步操作,组件中使用this.$store.commit调用

辅助函数:mapState、mapMutations、mapGetters、mapActions,它们的使用我们可以配合ES6的展开运算符将其与局部计算属性或方法混合使用

 import {mapState、mapMutations、mapGetters、mapActions} from ‘vuex’
compoted:{
...mapState({})
}
compoted:{
...mapGetters({})
}
methods:{
...mapActions({})
}
methods:{
...mapMutations({})
}

在这里插入图片描述

Vue-router使用

面试考点并不多(前提是熟悉Vue)
路由模式(hash、H5 history)
路由配置(动态路由、懒加载)

Vue-router路由模式

在这里插入图片描述

hash模式(默认),如http://abc.com/#/user/10
H5 history模式,如http://abc.com/user/20
后者需要server端支持,因此无特殊需求可选择前者
在这里插入图片描述
H5 history模式404不会跳转,需要配置404情况
在这里插入图片描述

Vue-router路由配置

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值