Vue学习笔记

编程知识 更新时间:2023-04-25 07:57:04

文章目录

  • 1.1 模板语法
    • 1.插值语法
    • 2.指令语法
      • v-bind指令
      • v-model指令
      • v-for指令
      • v-on指令
        • Vue中的事件修饰符
        • 键盘事件
      • v-if v-else-if v-else指令
      • v-show指令
      • v-text指令
      • v-html指令
      • v-cloak指令
      • v-once指令
      • v-pre指令
  • 1.2 计算属性
  • 1.3 侦听属性
  • 1.4 过滤器
  • 1.5 Vue生命周期
  • 2.1 组件化编程
    • 1. 定义组件
    • 2. 注册组件
    • 3. 使用组件
    • 4. VueComponent
  • 3.1 Vue CLI
    • 1. 具体步骤
    • 2.脚手架文件结构
    • 3.render函数
    • 4.ref属性
    • 5.props配置项
    • 6.mixin混入
    • 7.plugin插件
    • 8.Scoped
    • 9.本地存储
    • 10.组件的自定义事件
      • **1.绑定自定义事件**
      • **2.触发自定义事件**
      • **3.解绑自定义事件**
    • 11.全局事件总线
      • 1.定义全局事件总线
      • 2.使用全局事件总线
      • 3.解绑事件
    • 12.消息的订阅与发布
      • 1.安装pubsub
      • 2.引入pubsub
      • 3.使用pubsub:
    • 13.$nextTick
    • 14.过度与动画
      • 1.样式
      • 2.使用
    • 15.Ajax
      • 1.axios
      • 2.vue-resource
    • 16.slot插槽
      • 1.默认插槽
      • 2.具名插槽
      • 3.作用域插槽
  • 3.1 Vuex
    • 1.Vuex是什么
    • 2.什么时候使用Vuex
    • 3.Vuex原理图
    • 4.搭建Vuex环境
    • 5.getter配置项
    • 6.4个map方法的使用
      • 1.mapState
      • 2.mapGetters
      • 3.mapActions
      • 4.mapMutations
      • 5.模块化+命名空间
  • 4.1 Vue Router
    • 1.vue-router
    • 2.SPA
    • 3.路由
      • **什么是路由?**
      • **路由的分类**
        • 后端路由
        • 前端路由
    • 4.使用
        • **基本路由:**
        • **多级路由:**
    • 5.query
    • 6.命名路由
    • 7.params
    • 8.路由的props配置
    • 9.replace
    • 10.编程式路由导航
    • 11.缓存路由组件
    • 12.activated deactivated
    • 13.路由守卫
      • 分类:
        • 全局守卫
        • 独享守卫
        • 组件内守卫
    • 14.路由器的两种工作模式
  • 5.1Vue UI组件库
    • 常用的UI组件库
    • Element UI
      • **全部样式:**
      • **按需引入:**

1.1 模板语法

Vue模板语法包括两大类

1.插值语法

写法:{{xxx}},xxx是js表达式,可以直接读取data内容

2.指令语法

v-bind指令

单向绑定,数据只能从data流向页面

写法:

<a v-bind:href=""></a>
<a :href=""></a>

v-model指令

双向数据绑定,数据不仅能从data流向页面,还能从页面流向data

写法:

<input type="text" v-model="name"></input>

v-for指令

用于展示列表数据

注意:key可以是index,更好的是遍历对象的唯一标识

写法:

<li v-for="(item, index) in items" :key="index">
    {{key}}:{{value}}
</li>

v-on指令

绑定事件监听

写法:

<button @click="xxx">点我</button>
<button v-on:click="xxx($event)">点我</button> //可以传参

用法:

1.事件的回调需要配置在methods对象中,最终会在vm

2.methods中配置的函数,不能使用箭头函数,否则this就不是vm了

3.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或者组件实列对象

Vue中的事件修饰符

prevent阻止默认事件
stop阻止事件冒泡
once事件只能触发一次
capture使用事件的捕获模式
self只有event.target是当前操作的元素时才触发事件
passive事件的默认行为立即执行,无需等待事件回调执行完毕

键盘事件

Vue常用的按键别名

按键别名代码中
回车enter@keyup.enter=“xxx”
删除delete@keyup.delete=“xxx”
退出esc@keyup.esc=“xxx”
空格space@keyup.space=“xxx”
换行tab@keydown.tab=“xxx”
up@keyup.up=“xxx”
down@keyup.down=“xxx”
left@keyup.left=“xxx”
right@keyup.right=“xxx”

v-if v-else-if v-else指令

条件渲染

写法:

<div v-if="表达式"></div>
<div v-else-if="表达式"></div>
<div v-else="表达式"></div>

用法:

切换频率较低的场景,因为不展示的DOM元素直接被移除

v-show指令

写法:

<div v-show="表达式"></div>

用法:

切换频率较高的场景,不展示的DOM未被移除,仅仅是使用样式隐藏display:none

v-text指令

向其所在的节点中渲染文本内容

写法:

<div v-text="name"></div>

与插值语法的区别:

v-text会替换掉节点中的内容,{{xxx}}则不会,更灵活

v-html指令

向指定节点中渲染包含html结构的内容

写法:

<div v-html="name"></div>

name:'<h3>你好啊</h3>'

呈现:h3标签的你好啊

v-cloak指令

本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性

使用css配合v-cloak可以解决网速慢时展示出{{xxx}}的问题

写法:

<h2 v-cloak>{{xxx}}</h2>

v-once指令

所在节点初次动态渲染后,就视为静态内容了

以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

写法:

<h2 v-once>{{xxx}}</h2>	//数据改变不会改变其值

v-pre指令

跳过v-pre所在节点的编译过程

可利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译

写法:

<h2 v-pre>Vue</h2>

1.2 计算属性

语法:

computed:{

}

定义:

要用的属性不存在,需要通过已有属性计算得来

原理:

底层借助了Object.defineproperty()方法提供的getter和setter

备注:

1.计算属性最终会出现在vm上,直接读取使用即可

2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变

3.如果计算属性不考虑修改,可以使用计算属性的简写形式

写法:

  <script>
     var vue = new Vue({
      el : '#root',
      data : { 
        firstName:'张',
        lastName:'三'
       },
      methods : {
        
       },
       computed:{
         //完整写法
        // fullName:{
        //   get(){
        //     console.log('get被调用了')
        //     return this.firstName+'-'+this.lastName
        //   },
        //   set(value){
        //     var arr = value.split('-');
        //     this.firstName=arr[0];
        //     this.lastName=arr[1]
        //   }
        // }
        //简写
        fullName(){
          return this.firstName+'-'+this.lastName
        }
       }   
    });
  </script>

1.3 侦听属性

语法:

//第一种
watch:{

}
//第二种
vm.$watch()

定义:

当被监听的属性变化时,回调函数自动调用,进行相关操作

配置项属性:

immediate:false //改为true,则初始化调用一次
deep:true //可以监听对象内部值的改变

注意:

1.监听的属性必须存在,才能进行监视,既可以监视data,也可以监视计算属性

2.使用watch时根据监视数据的具体结构,决定是否采用深度监视

计算属性VS侦听属性

区别:

1puted能完成的功能,watch都可以完成

2.watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作

两个重要的小原则:

1.所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象

2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象

1.4 过滤器

定义:

要对显示的数据进行特定格式化后在显示

用法:

//注册
Vue.filter(name,callback) //全局过滤器
new Vue ({//局部过滤器
    filters:{
        过滤器名称(val,规则){}
    }
})  
//实现
{{数据 | 过滤器名称 | 过滤器名称}}

1.5 Vue生命周期

生命周期

1.又名生命周期回调函数、生命周期函数、生命周期钩子

2.是什么?Vue在关键时刻帮我们调用的一些特殊名称的函数

3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的

4.生命周期函数中的this指向是vm或组件实例对象

原理图:

写法:

    <script>
         var vm = new Vue({
            el : '#root',
            data : {  },
            methods : { }  ,
            beforeCreate() {
                
            },  
            created() {
                
            },
            beforeMount() {
                
            },
            mounted() {
  //常用来发送ajax请求、启动定时器,绑定自定义事件、订阅消息等初始化操作
            },
            beforeUpdate() {
                
            },
            updated() {
                
            },
            beforeDestroy() {
 //清除定时器、解绑自定义事件、取消订阅消息等收尾工作               
            },
            destroyed() {
                
            },
        });
    </script>

2.1 组件化编程

1. 定义组件

使用Vue.extend(options)创建,其中options和new Vue(options)时传入的options几乎一样,但也有点区别:

a.el不要写,因为最终所有的组件都要经过一个vm的管理,由vm中的el才决定服务哪个容器

b.data必须写成函数,避免组件被复用时,数据存在引用关系

写法:

const school = Vue.extend({
            template: `

            `,
            data() {
                return {
                    
                }
            },
            methods: {
                
            }
        })

2. 注册组件

局部注册:

var vm = new Vue({
            el: '#root',
            components: {
               
            }
        });

全局注册:

Vue.component('组件名',组件)

3. 使用组件

编写组件标签如:<School></School>

组件注意事项

一个单词组成

第一种写法(首字母小写):school

第二种写法(首字母大写):School

多个单词组成

第一种写法(kebab-case命名):my-school

第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)

组件标签

第一种写法:

第二种写法:(需要Vue脚手架支持)

4. VueComponent

组件实例对象vc

重要的内置关系:

VueComponent.prototype._proto_ === Vue.prototype

3.1 Vue CLI

1. 具体步骤

全局安装 @Vue/cli npm install -g @vue/cli

切换到创建项目的目录,使用命令创建项目 vue create xxx

选择使用vue的版本

启动项目 npm run serve

打包项目 npm run build

2.脚手架文件结构

.文件目录
├── node_modules 
├── public
│   ├── favicon.ico: 页签图标
│   └── index.html: 主页面
├── src
│   ├── assets: 存放静态资源
│   │   └── logo.png
│   │── component: 存放组件
│   │   └── HelloWorld.vue
│   │── App.vue: 汇总所有组件
│   └── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件 
├── README.md: 应用描述文件
└── package-lock.json: 包版本控制文件

3.render函数

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  el:'#app',
  // render函数功能:将App组件放入容器中
  // 简写形式
  render: h => h(App),
  // 完整形式
  // render(createElement){
  //   return createElement(App)
  // }
})

4.ref属性

ref被用来给元素或子组件注册引用信息(id的替代者)

使用方式:

<h1 v-text="msg" ref="title"></h1>	//html标签上,获取的是DOM元素
<School ref="sch"/>	//组件标签上,获取的是组件实例对象vc

//获取
this.$refs.xxx

5.props配置项

props让组件接收外部传过来的数据

适用于:

父组件 ==> 子组件 通信

子组件 ==> 父组件 通信 (要求父组件先给子组件一个函数)

传递数据:

<Student name="李四" sex="男" :age="18"></Student>

接收数据:

    //简单接收
    props:['name','sex','age']

    //接收数据的同时并且对类型进行限制
    // props:{
    //     name:String,
    //     sex:String,
    //     age:Number
    // }

    //接收数据的同时对类型进行限制并设置默认值
    /* props:{
        name:{
            type:String,
            required:true,
        },
        sex:{
            type:String,
            required:false,
            default:'男'
        },
        age:{
            type:Number,
            required:false,
            default:99
        }
    } */

备注:props是只读的,若需要修改,复制props内容到data中,然后修改data中的数据

6.mixin混入

可以把多个组件共用的配置提取成一个混入对象

定义混入:

export const mixin = {
    methods: {
        showName() {
            alert(this.name)
        }
    },
}

使用混入:

//全局混入
Vue.mixin(混入名)

//局部混入
mixins:[‘xxx]

注意事项:

a.组件和混入对象含有同名选项时,这些选项将以恰当的方式进行"合并",在发生冲突时以组件优先

b.同名生命周期钩子将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用

7.plugin插件

用于增强Vue

本质:包含install方法的一个对象,install第一个参数是Vue,第二个以后的参数是插件使用者传递的数据

定义插件:

export default {
    install(Vue){
        Vue.filter('mySlice',function(params) {
            return params.slice(0,4)
        })
    }
}

使用插件:

Vue.use(插件)

8.Scoped

作用:

让样式在局部生效,防止冲突

写法:

<style scoped>

9.本地存储

游览器通过Window.sessionStorage 和Window.localStorage属性来实现本地存储机制

相关API:

方法含义
xxxStorage.setItem(‘key’,‘value’)该方法接受一个键和值作为参数,会把键值添加到存储中,如果键名存在,则更新对应的值
xxxStorage.getItem(‘key’)该方法接收一个键名作为参数,返回键名对应的值
xxxStorage.removeItem(‘key’)该方法接收一个键名作为参数,并把该键名从存储中删除
xxxStorage.clear()该方法会清空存储中的所有数据

注意事项:

SessionStorage存储的内容会随着游览器窗口关闭而消失

LocalStorage存储的内容,需要手动清楚才会消失

xxxStorage.getItem(‘key’)如果key对应的value获取不到,返回值则为null

10.组件的自定义事件

组件间通信的方式,适用于:子组件 ===> 父组件

1.绑定自定义事件

子组件想给父组件传数据,需要在父组件中给子组件绑定一个自定义事件(事件的回调在父组件中)

第一种方式:

<School @事件名="方法"></School>
<School v-on:事件名="方法"></School>

第二种方式:

<子组件标签 ref="xxx"></子组件标签>
mounted(){
    //回调函数要么配置在methods中,要么用箭头函数,否则this指向会出问题
	this.$refs.子组件.$on('事件名', 回调函数)
    //this.$refs.子组件.$once('事件名', 回调函数)	//事件触发一次
    }

2.触发自定义事件

this.$emit('事件名', 数据)

3.解绑自定义事件

this.$off('事件名')	//解绑一个自定义事件
this.$off(['事件名','事件名'])	//解绑多个自定义事件
this.$off()	//解绑所有的自定义事件

11.全局事件总线

一种可以在任意组件间通信的方式,本质上就是一个对象,它必须满足以下条件:

所有的组件对象都必须能看见他

这个对象必须能够使用**$on $emit $off** 方法去绑定、触发和解绑事件

1.定义全局事件总线

new Vue({
   	...
   	beforeCreate() {
   		Vue.prototype.$bus = this // 安装全局事件总线,$bus 就是当前应用的 vm
   	},
    ...
})

2.使用全局事件总线

接收数据方:

组件想接收数据,则在该组件中给$bus绑定自定义事件,事件的回调留在该组件自身

export default {
    methods(){
        demo(data){...}
    }
    ...
    mounted() {
        //第一种 配合methods使用
        this.$bus.$on('xxx',this.demo)
        
        //第二种 使用箭头函数
        this.$bus.$on('xxx', (data) => {
               ...
            })
    }
}

提供数据方:

this.$bus.$emit('xxx',提供给的数据)

3.解绑事件

在beforeDestroy钩子中,用$off()去解绑当前组件所用到的事件

beforeDestroy() {
            this.$bus.$off('事件名')
        },

12.消息的订阅与发布

消息订阅与发布也是一种组件间通信的方式,适用于任意组件间通信

使用步骤:

1.安装pubsub

npm i pubsub-js

2.引入pubsub

import pubsub from 'pubsub-js'

3.使用pubsub:

接收数据方(订阅):

哪个组件想接收数据,则在该组件订阅消息,订阅的回调在自身

export default {
    methods: {
        demo(msgName, data) {...}
    }
    ...
    mounted() {
			this.pid = pubsub.subscribe('xxx',this.demo)
    }
}

发送数据方(发布):

pubsub.publish('xxx',data)

取消订阅:

beforeDestroy() {
            pubsub.unsubscribe(pid)	//pid为订阅方返回的id值
        },

13.$nextTick

这是一个生命周期钩子

this.$nextTick(回调函数)在下一次DOM更新结束后指向其指定的回调

什么时候用?当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行

14.过度与动画

Vue封装的过度与动画:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名

1.样式

元素进入的样式元素离开的样式
进入的起点v-enter离开的起点v-leave
进入的过程中v-enter-active离开的过程中v-leave-active
进入的终点v-enter-to离开的终点v-leave-to

2.使用

使用包裹要过度的元素,并配置name属性,此时需要将上面的v换成name,如果需要让页面一开始就显示动画,需要加appear

15.Ajax

1.axios

安装:

npm install axios

配置:

vue.config.js添加配置

module.exports = {
	devServer: {
      proxy: {
      '/api1': {													// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',	// 代理目标的基础路径
        pathRewrite: {'^/api1':''},				// 代理往后端服务器的请求去掉 /api1 前缀
        ws: true,													// WebSocket
        changeOrigin: true,
        
      },
      '/api2': {
        target: 'http://localhost:5001',
        pathRewrite: {'^/api2': ''},
        changeOrigin: true
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

用法:

axios.get(`https://api.github/search/users?q=${this.keyWorld}`).then(
                    response => {
                        console.log('请求成功了', response.data)
                        this.$bus.$emit('updateListData', { isLoading: false, errMsg: '', users: response.data.items })
                    },
                    error => {
                        console.log('请求失败了')
                        this.$bus.$emit('updateListData', { isLoading: false, errMsg: error.message, users: [] })
                    }
                )

2.vue-resource

安装:

npm i vue-resource

用法:

this.$http.get(`https://api.github/search/users?q=${this.keyWorld}`).then(
                    response => {
                        console.log('请求成功了', response.data)
                        this.$bus.$emit('updateListData', { isLoading: false, errMsg: '', users: response.data.items })
                    },
                    error => {
                        console.log('请求失败了')
                        this.$bus.$emit('updateListData', { isLoading: false, errMsg: error.message, users: [] })
                    }
                )

16.slot插槽

插槽:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式。

适用于:父组件 ===> 子组件

1.默认插槽

父组件中:
        <Category>
           <div>html结构1</div>
        </Category>
子组件中:Category
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot>插槽默认内容...</slot>
            </div>
        </template>

2.具名插槽

父组件指明放入子组件的哪个插槽

父组件中:
        <Category>
            <template slot="center">
              <div>html结构1</div>
            </template>

            <template v-slot:footer>
               <div>html结构2</div>
            </template>
        </Category>
子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot name="center">插槽默认内容...</slot>
               <slot name="footer">插槽默认内容...</slot>
            </div>
        </template>

3.作用域插槽

scope用于父组件接收子组件在插槽放入的数据

父组件中:
        <Category>
            <template scope="scopeData">
                <!-- 生成的是ul列表 -->
                <ul>
                  <li v-for="g in scopeData.games" :key="g">{{g}}</li>
                </ul>
            </template>
        </Category>

        <Category>
            <template slot-scope="scopeData">
                <!-- 生成的是h4标题 -->
                <h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
            </template>
        </Category>
子组件中:
        <template>
            <div>
                <slot :games="games"></slot>
            </div>
        </template>
		
        <script>
            export default {
                name:'Category',
                props:['title'],
                //数据在子组件自身
                data() {
                    return {
                        games:['红色警戒','穿越火线','劲舞团','超级玛丽']
                    }
                },
            }
        </script>

3.1 Vuex

1.Vuex是什么

专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信

2.什么时候使用Vuex

多个组件依赖于同一状态

来自不同组件的行为需要变更同一状态

3.Vuex原理图

4.搭建Vuex环境

安装:

npm i vuex

配置:

src/store/index.js,该文件创建Vuex最为核心的store

import Vue from 'vue'
import Vuex from 'vuex'	// 引入Vuex

Vue.use(Vuex)	// 应用Vuex插件

const actions = {}		// 准备actions——用于响应组件中的动作
const mutations = {}	// 准备mutations——用于操作数据(state)
const state = {}			// 准备state——用于存储数据

// 创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})

src/main.js中创建vm时传入store配置项

import Vue from 'vue'
import App from './App.vue'
import store from './store'	// 引入store

Vue.config.productionTip = false

new Vue({
	el: '#app',
	render: h => h(App),
	store,										// 配置项添加store
	beforeCreate() {
		Vue.prototype.$bus = this
	}
})

使用:

组件中修改vuex中的数据:

$store.dispatch('action中的方法名',数据)
$store.commit('mutations中的方法名',数据)

若没有网络请求或其他业务逻辑,组件可越过actions,即不写dispatch,直接写commit

组件中读取vuex中的数据:

$store.state.数据

5.getter配置项

概念:

当state中的数据需要经过加工后在使用时,可以使用getters加工,相当于全局计算属性

使用:

......

const getters = {
	bigSum(state){
		return state.sum * 10
	}
}

// 创建并暴露store
export default new Vuex.Store({
	......
	getters
})

组件中读取数据:

$store.getters.方法名

6.4个map方法的使用

1.mapState

用于帮助映射state中的数据为计算属性

computed: {
  	// 借助mapState生成计算属性:sum、school、subject(对象写法一)
  	...mapState({sum:'sum',school:'school',subject:'subject'}),

  	// 借助mapState生成计算属性:sum、school、subject(数组写法二)
  	...mapState(['sum','school','subject']),
},

2.mapGetters

用于帮助映射getters中的数据为计算属性

computed: {
    //借助mapGetters生成计算属性:bigSum(对象写法一)
    ...mapGetters({bigSum:'bigSum'}),

    //借助mapGetters生成计算属性:bigSum(数组写法二)
    ...mapGetters(['bigSum'])
},

3.mapActions

用于帮助生成与actions对话的方法,即包含$store.dispatch(xxx)的函数

methods:{
    //靠mapActions生成:incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

    //靠mapActions生成:incrementOdd、incrementWait(数组形式)
    ...mapActions(['jiaOdd','jiaWait'])
}

4.mapMutations

用于帮助生成与mutations对话的方法,即包含$storemit(xxx)的函数

methods:{
    //靠mapActions生成:increment、decrement(对象形式)
    ...mapMutations({increment:'JIA',decrement:'JIAN'}),
    
    //靠mapMutations生成:JIA、JIAN(对象形式)
    ...mapMutations(['JIA','JIAN']),
}

注意:mapActions与mapMutations使用时,若需要传递参数,需要**在模板中绑定事件时传递好参数**,否则参数是事件对象

5.模块化+命名空间

目的:

让代码更好维护,让多种数据分类更加明确

修改store.js

为了解决不同模块命名冲突的问题,将不同模块添加namespaced:true,之后在不同页面中引入actions、mutations、getter时,需要加上所属的模块名

开启命名空间后,组件读取state的数据:

// 方式一:自己直接读取
this.$store.state.personAbout.list
// 方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),

开启命名空间后,组件读取getters的数据:

//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])

开启命名空间后,组件中调用dispatch:

//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

开启命名空间后,组件中调用mutations:

//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout'{increment:'JIA',decrement:'JIAN'}),

4.1 Vue Router

1.vue-router

Vue的一个插件库,专门用来实现SPA应用

2.SPA

单页Web的应用(single page web application, SPA)

整个应用只有一个完整的页面

点击页面中的导航链接不会刷新页面,只会做页面的局部刷新

数据需要通过ajax请求获取

3.路由

什么是路由?

一个路由就是一组映射关系(key-value)

key为路径,value可能是function或component

路由的分类

后端路由

理解:value是function,用于处理客户端提交的请求

工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应数据

前端路由

理解:value是component,用于展示页面内容

工作过程:当游览器的路径改变时,对应的组件就会显示

4.使用

安装:

npm i vue-router

应用插件:

Vue.use(VueRouter)

基本路由:

import VueRouter from 'vue-router'			// 引入VueRouter
import About from '../components/About'	// 路由组件
import Home from '../components/Home'		// 路由组件

// 创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
	routes:[
		{
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home
		}
	]
})

//暴露router
export default router

实现切换:

/**
<router-link></router-link> 游览器会被替换为a标签 
active-class可配置高亮样式
*/
<router-link active-class="active" to="/about">About</router-link>

展示位:

<router-view></router-view>

注意事项:

1.路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹

2.通过切换,隐藏了的路由组件,默认是被销魂掉的,需要的时候再去挂载

3.每个组件都有自己的**$route**属性,里面存储着自己的路由信息

4.整个应用只有一个** r o u t e r ∗ ∗ , 可 以 通 过 组 件 的 router**,可以通过组件的 routerrouter属性获取到

多级路由:

routes:[
	{
		path:'/about',
		component:About,
	},
	{
		path:'/home',
		component:Home,
		children:[ 					// 通过children配置子级路由
			{
				path:'news', 		// 此处一定不要带斜杠,写成 /news
				component:News
			},
			{
				path:'message',	// 此处一定不要写成 /message
				component:Message
			}
		]
	}
]

跳转(写完整路径):

<router-link to="/home/news">News</router-link>

5.query

路由的query参数

传递参数:

<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">跳转</router-link>
				
<!-- 跳转并携带query参数,to的对象写法(推荐) -->
<router-link 
	:to="{
		path:'/home/message/detail',
		query:{
		   id: m.id,
       	   title: m.title
		}
	}"
>跳转</router-link>

接收参数:

$route.query.id
$route.query.title

6.命名路由

作用:

可以简化路由的跳转

使用:

a.给路由命名

{
	path:'/demo',
	component:Demo,
	children:[
		{
			path:'test',
			component:Test,
			children:[
				{
          			name:'hello' // 给路由命名
					path:'welcome',
					component:Hello,
				}
			]
		}
	]
}

b.简化跳转

<!--简化前,需要写完整的路径 -->
<router-link to="/demo/test/welcome">跳转</router-link>

<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'hello'}">跳转</router-link>

<!--简化写法配合传递参数 -->
<router-link 
	:to="{
		name:'hello',
		query:{
		    id:666,
        	title:'你好'
		}
	}"
>跳转</router-link>

7.params

使用params参数时,需要配置路由,使用占位符声明接收params参数

配置:

{
	path:'/home',
	component:Home,
	children:[
		{
			path:'news',
			component:News
		},
		{
			component:Message,
			children:[
				{
					name:'xiangqing',
					path:'detail/:id/:title', //使用占位符声明接收params参数
					component:Detail
				}
			]
		}
	]
}

传递参数:

特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置

<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
				
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link 
	:to="{
		name:'xiangqing',
		params:{
		    id:666,
       	 	title:'你好'
		}
	}"
>跳转</router-link>

接收参数:

$route.params.id
$route.params.title

8.路由的props配置

作用:

让路由组件更方便的收到参数

写法:

{
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
	// props:{a:900}

	//第二种写法:props值为布尔值,为true时,则把路由收到的所有params参数通过props传给Detail组件
	// props:true
	
	//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
	props($route){
		return {
			id: $route.query.id,
			title: $route.query.title
		}
	}
}

案例:

路由配置:

import VueRouter from "vue-router";
import Home from '../pages/Home'
import About from '../pages/About'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'

export default new VueRouter({
  routes:[
    {
      path: '/about',
      component: About
    },
    {
      path:'/home',
      component:Home,
      children:[
        {
          path:'news',
          component:News
        },
        {
          path:'message',
          component:Message,
          children:[
            {
              name:'xiangqing',
              path:'detail/:id/:title',
              component:Detail,
              // props的第一种写法,值为对象,
              // 该对象中的所有key-value都会以props的形式传给Detail组件
              // props:{a:1,b:'hello'}

              // props的第二种写法,值为布尔值,
              // 若布尔值为真,会把该路由组件收到的所有params参数,以props的形式传给Detail组件
              // props:true

              // props的第三种写法,值为函数
              props(params) { // 这里可以使用解构赋值
                return {
                  id: params.id,
                  title: params.title,
                }
              }
            }
          ]
        }
      ]
    }
  ]
})

传递参数:

<template>
	<div>
    <ul>
      <li v-for="m in messageList" :key="m.id">
        <router-link :to="{
                name:'xiangqing',
                params:{
                    id:m.id,
                    title:m.title
                }
         }">
          	{{m.title}}
  			</router-link>&nbsp;&nbsp;
  		</li>
  	</ul>
    <hr/>
    <router-view></router-view>
  </div>
</template>

<script>
    export default {
        name:'News',
        data(){
            return{
                messageList:[
                    {id:'001',title:'消息001'},
                    {id:'002',title:'消息002'},
                    {id:'003',title:'消息003'}
                ]
            }
        }
    }
</script>

接收参数:

<template>
    <ul>
        <li>消息编号:{{ id }}</li>
        <li>消息标题:{{ title }}</li>
    </ul>
</template>

<script>
    export default {
        name:'Detail',
        props:['id','title']
    }
</script>

9.replace

作用:

控制路由跳转时操作游览器历史记录的模式

游览器的历史记录的两种写入方式:

push:是追加历史记录,默认方式

replace:是替换当前记录

开启replace模式:

<router-link :replace="true" >News</router-link>
<router-link replace >News</router-link>

10.编程式路由导航

作用:

不借助router-link实现路由跳转,让路由跳转更加灵活

API:

写法
this.$router.push({})内穿的对象与router-link中的to相同
this.$router.reolace({})
this.$router.forward()前进
this.$router.back()后退
this.$router.go(n)可前进也可后退,n为正数前进n,负数为后退n

示例:

this.$router.push({
	name:'xiangqing',
  params:{
    id:xxx,
    title:xxx
  }
})

this.$router.replace({
	name:'xiangqing',
  params:{
    id:xxx,
    title:xxx
  }
})


<template>
	<div class="col-xs-offset-2 col-xs-8">
		<div class="page-header">
			<h2>Vue Router Demo</h2>
			<button @click="back">后退</button>
			<button @click="forward">前进</button>
			<button @click="test">测试一下go</button>
		</div>
	</div>
</template>

<script>
	export default {
		name:'Banner',
		methods:{
			back(){
				this.$router.back()
			},
			forward(){
				this.$router.forward()
			},
			test(){
				this.$router.go(3)
			}
		},
	}
</script>

11.缓存路由组件

作用:

让不展示的路由组件保持挂载,不被销魂

示例:

// 缓存一个路由组件
<keep-alive include="News"> // include中写想要缓存的组件名,不写表示全部缓存
    <router-view></router-view>
</keep-alive>

// 缓存多个路由组件
<keep-alive :include="['News','Message']"> 
    <router-view></router-view>
</keep-alive>

12.activated deactivated

概念:

activated和deactivated是路由组件所独有的两个钩子,用于捕获路由组件的激活状态

使用:

activated:路由组件被激活时触发

deactivated:路由组件失活时触发

示例:

<template>
    <ul>
        <li :style="{opacity}">欢迎学习vue</li>
        <li>news001 <input type="text"></li>
        <li>news002 <input type="text"></li>
        <li>news003 <input type="text"></li>
    </ul>
</template>

<script>
    export default {
        name:'News',
        data(){
            return{
                opacity:1
            }
        },
        activated(){
            console.log('News组件被激活了')
            this.timer = setInterval(() => {
                this.opacity -= 0.01
                if(this.opacity <= 0) this.opacity = 1
            },16)
        },
        deactivated(){
            console.log('News组件失活了')
            clearInterval(this.timer)
        }
    }
</script>

13.路由守卫

作用:

对路由进行权限控制

分类:

全局守卫

// 全局前置守卫:初始化时、每次路由切换前执行
router.beforeEach((to,from,next) => {
	console.log('beforeEach',to,from)
	if(to.meta.isAuth){ // 判断当前路由是否需要进行权限控制
		if(localStorage.getItem('school') === 'atguigu'){ // 权限控制的具体规则
			next()	// 放行
		}else{
			alert('暂无权限查看')
		}
	}else{
		next()	// 放行
	}
})

// 全局后置守卫:初始化时、每次路由切换后执行
router.afterEach((to,from) => {
	console.log('afterEach',to,from)
	if(to.meta.title){ 
		document.title = to.meta.title //修改网页的title
	}else{
		document.title = 'vue_test'
	}
})

独享守卫

beforeEnter(to,from,next){
	console.log('beforeEnter',to,from)
    if(localStorage.getItem('school') === 'atguigu'){
        next()
    }else{
        alert('暂无权限查看')
    }
}

组件内守卫

//进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {... next()},

//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {... next()},

14.路由器的两种工作模式

1.对于一个url来说,什么是hash值?

#及后面的内容就是hash值

2.hash值

不会包含在HTTP请求中,即:hash值不会带给服务器

3.hash模式

地址中永远带着#号,不美观

若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法

兼容性较好

4.history模式

地址干净,美观

兼容性和hash模式相比略差

应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题

const router =  new VueRouter({
	mode:'history',
	routes:[...]
})

export default router

5.1Vue UI组件库

常用的UI组件库

移动端PC端
VantElement UI
Cube UIIView UI
Mint UI
NutUI

Element UI

安装:

npm i element-ui -S

使用:

全部样式:

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';							// 引入ElementUI组件库
import 'element-ui/lib/theme-chalk/index.css';	// 引入ElementUI全部样式

Vue.config.productionTip = false

Vue.use(ElementUI)	// 使用ElementUI

new Vue({
    el:"#app",
    render: h => h(App),
})

按需引入:

安装:

npm i babel-plugin-component -D

修改babel-config-js

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    ["@babel/preset-env", { "modules": false }]
  ],
  plugins: [
    [
      "component",
      {        
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

使用:

import Vue from 'vue'
import App from './App.vue'
import { Button,Row } from 'element-ui'	// 按需引入

Vue.config.productionTip = false

Vue.component(Button.name, Button);
Vue.component(Row.name, Row);
/* 或写为
 * Vue.use(Button)
 * Vue.use(Row)
 */

new Vue({
    el:"#app",
    render: h => h(App),
})

更多推荐

Vue学习笔记

本文发布于:2023-04-19 03:24:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/926ab103d5355880c7c65c58241750f7.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学习笔记   Vue

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!

  • 87068文章数
  • 19103阅读数
  • 0评论数