vue2 vue-cli vue-router vuex

Vue2

插值表达式

  • 利用表达式进行插值渲染,将数据渲染到页面中。

  • 语法:{{ 表达式 }}

  • PS:

    • 使用的数据要存在
    • 支持的是表达式,不是语句 iffor
    • 不能在标签属性中使用{{ }}

v-show和v-if

  • v-show底层原理:切换cssdisplay: none来控制显示隐藏
    • 场景:频繁切换显示隐藏的场景
  • v-if底层原理:根据判断条件控制元素的创建和移除(条件渲染)
    • 场景:要么显示,要么隐藏,不频繁切换的场景

v-on

  • 作用:注册事件 = 添加监听 + 提供处理逻辑
  • 语法①:v-on:事件名="内联语句"
    • 简写:@事件名
  • 语法②:v-on:事件名="methods中的函数名"
    • methods函数内的this指向Vue实例

v-bind

  • 作用:动态设置html的标签属性,如src、url、title...
  • 语法:v-bind:属性名="表达式"
  • 可以简写,如v-bind:src可以简写为:src

v-for

  • 作用:基于数据循环,多次渲染整个元素(数组、对象、数字…

  • 语法:v-for="(item,index) in 数组"

    • item每一项,index下标
    • index可以省略,v-for="item in 数组"
  • key作用:给元素添加唯一标识,便于Vue进行列表项的正确排序服用

    • v-for的默认行为会尝试原地修改元素(就地复用)
    • key的值只能是字符串或数字类型
    • <li v-for="(item,index) in xxx" :key="唯一值">

v-model

  • 作用:给表单元素使用,双向数据绑定,可以快速获取或设置表单元素内容

    • 数据变化,视图自动更新
    • 试图变化,数据自动更新
  • 语法:v-model='变量'

  • v-model应用于其他表单元素,它会根据控件类型自动选取正确的方法来更新元素

    • radio前置理解:
      • name:给单选框加上name属性,就可以分组(同一组互相会互斥
      • value:给单选框加上value属性,用于提交给后台的数据
    • select前置理解:
      • option需要设置value值,提交给后台
      • selectvalue值,关联了选中的optionvalue
  • 原理:本质上是个语法糖

    • 例如应用到输入框上,就是value属性和input事件的合写。

    • 数据变,视图跟着变 :value

    • 视图变,数据跟着变 @input

    • $event用于在模板中,获取事件的形参

记事本小案例

  • 1、列表渲染
    • v-for key的设置 {{}}插值表达式
  • 2、删除功能
    • v-on调用传参 filter过滤,覆盖修改原数组
  • 3、添加功能
    • v-model绑定 unshift修改原数组添加
  • 4、底部统计和清空
    • 数组.length累计长度
    • 覆盖数组清空列表
    • v-show控制隐藏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/index.css" />
<title>记事本</title>
</head>
<body>

<!-- 主体区域 -->
<section id="app">
  <!-- 输入框 -->
  <header class="header">
    <h1>记事本</h1>
    <!-- @keyup.enter 监听键盘回车事件 -->
    <input @keyup.enter="add" v-model="todoName" placeholder="请输入任务" class="new-todo" />
    <button @click="add" class="add">添加任务</button>
  </header>
  <!-- 列表区域 -->
  <section class="main">
    <ul class="todo-list">
      <li class="todo" v-for="(item,index) in list" :key="item.id">
        <div class="view">
          <span class="index">{{ index + 1 }}.</span> <label>{{ item.name }}</label>
          <button @click="del(item.id)" class="destroy"></button>
        </div>
      </li>
    </ul>
  </section>
  <!-- 统计和清空  如果没有任务了 底部隐藏掉 v-show -->
  <footer class="footer" v-show="list.length > 0">
    <!-- 统计 -->
    <span class="todo-count">合 计:<strong> {{ list.length }} </strong></span>
    <!-- 清空 -->
    <button @click="clear" class="clear-completed">
      清空任务
    </button>
  </footer>
</section>

<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  //添加功能
  //1.通过v-model绑定输入框,实时获取表单元素的内容
  //2.点击按钮,进行新增,往数组最前面加 unshift

  const app = new Vue({
    el: '#app',
    data: {
      todoName: '',
      list:[
        {id: 1, name: '跑步800m'},
        {id: 2, name: '打球1h'},
        {id: 3, name: '看半本书'},
      ]
    },
    methods: {
      del(id){
        this.list = this.list.filter(item => item.id !== id)
      },
      add(){
        if(this.todoName.trim() === ''){
          alert('请输入任务')
          return
        }
        this.list.unshift({
          id: +new Date(),
          name: this.todoName
        })
        this.todoName = ''
      },
      clear(){
        this.list = []
      }
    },
  })

</script>
</body>
</html>

指令的修饰符

  • @keyup.enter:监听键盘回车事件
    • 相当于帮我们加了e.key === enter这个判断
  • v-model修饰符
    • .trim:去首尾空格
    • .number:尝试转成数字(能转的就转
  • @事件名.stop:阻止冒泡
  • @事件名.prevent:阻止默认行为

v-bind对样式控制的增强

  • 操作class

    • 语法::class="对象/数组"

      • 对象:键就是类名,值就是布尔值。值为true,就有这个类,否则就没有

        <div class="box" :class="{类名1: 布尔值, 类名2: 布尔值}"></div>

      • 使用场景:一个类名,来回切换(京东导航栏

      • 数组:数组中所有的类,都会添加到盒子里,本质是一个class列表

        <div class="box" :class="[类名1, 类名2]"></div>

      • 使用场景:批量添加或删除类

  • 操作style

    • 语法::style="样式对象"

      <div class="box" :style="{css属性名1: css属性值, css属性名2: css属性值}"></div>

    • 使用场景:某个具体属性的动态设置(进度条

计算属性

  • 概念:基于现有的数据,计算出来的新属性。依赖的数据变化,自动重新计算。

  • 语法:

    • 1、声明在computed配置项中,一个计算属性对应一个函数

      computed: {
      	计算属性名 () {
      		基于现有数据,编写求值逻辑
      		return 结果
      	}
      }
      
    • 2、使用起来和普通属性一样:{{ 计算属性名 }}

  • computed vs methods

    • computed作用:封装了一段对于数据的处理,求得一个结果。
      • 缓存特性(提升性能):计算属性会对计算出来的结果缓存,再次使用直接读取缓存。只有依赖项变化了,才会自动重新计算,然后再次缓存。
    • methods作用:给实例提供一个方法,调用以处理业务逻辑。
  • 计算属性默认的缩写,只能读取访问,不能修改。如果要修改,就要写计算属性的完整写法。

    • 执行get会返回求值的结果
    • 被修改赋值时会执行set,修改的值传递给set方法的形参
    computed: {
    	计算属性名: {
    		get(){
    			一段代码逻辑(计算逻辑
    			return 结果
    		},
    		set(修改的值){
    			一段代码逻辑(修改逻辑
    		}
    	}
    }
    

watch监听器

  • 作用:监视数据变化,执行一些业务逻辑或异步操作。

  • 语法:

    • 1.简单写法:简单类型数据,直接监视

      watch:{
      	//该方法会在数据变化时,触发执行
      	数据属性名(newValue, OldValue){
      		一些业务逻辑或异步操作
      	},
      	'对象.属性名'(newValue, OldValue){
      		一些业务逻辑或异步操作
      	}
      }
      
      • oldValue一般不用,可以不写
    • 2.完整写法:添加额外配置项

      • deep: true:对复杂类型深度监视
      • immediate: true:初始化立刻执行一次handler方法
      watch: {
      	监视对象: {
      		deep: true, //监视多个 深度监视
      		immediate: true, //一进入页面就触发handler
      		handler(newValue){
      			一些业务逻辑或异步操作
      		}
      	}
      }
      

生命周期

  • Vue生命周期:一个Vue实例从创建到销毁的整个过程。

    • 1.创建:响应式数据
    • 发送初始化渲染请求(越早越好
    • 2.挂载:渲染模板
    • 操作dom(至少dom要渲染出来
    • 3.更新:数据修改,更新视图(循环多次
    • 4.销毁:销毁实例
  • 生命周期函数(钩子函数):自动运行的一些函数
    在这里插入图片描述

记账清单案例

  • 基本渲染:

    • 1.created请求数据(封装渲染方法)
    • 2.拿到数据,存到data的响应式数据中
    • 3.结合数据进行渲染 v-for
    • 4.消费统计 => 计算属性
            computed: {
              totalPrice(){
                return this.list.reduce((sum, item) => sum + item.price, 0)
              }
            },
            async created(){
              // const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
              //   params: {
              //   creator: 'kk'
              //   }
              // })
              this.list = res.data.data
              this.getList()
            },
    
  • 添加功能:

    • 1.收集表单数据 v-model
    • 2.给添加按钮注册点击事件,发送添加请求
    • 3.重新渲染
             async add(){
                if(!this.name){
                  alert('請輸入消費名稱')
                  return
                }
                if(typeof this.price !== 'number'){
                  alert('请输入正确数字')
                  return
                }
    
                //發送請求
                const res = await axios.post('https://applet-base-api-t.itheima.net/bill,', {
                  creator: 'kk',
                  name: this.name,
                  price: this.price
                })
                //重新渲染
                this.getList()
    
                this.name = ''
                this.price = ''
              },
    
  • 删除功能:

    • 1.注册点击事件,传参数id
    • 2.根据id发送删除请求
    • 3.重新渲染
              async del(id){
                const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`)
                this.getList()
              }
    
  • 饼图渲染:

    • 1.初始化一个饼图echarts.init(dom) mounted钩子实现
    • 2.根据数据实时更新饼图echarts.setOption({...})
    mounted () {
              this.myChart = echarts.init(document.querySelector('#main'))
              this.myChart.setOption({
                // 大标题
                title: {
                  text: '消费账单列表',
                  left: 'center'
                },
                // 提示框
                tooltip: {
                  trigger: 'item'
                },
                // 图例
                legend: {
                  orient: 'vertical',
                  left: 'left'
                },
                // 数据项
                series: [
                  {
                    name: '消费账单',
                    type: 'pie',
                    radius: '50%', // 半径
                    data: [
                      // { value: 1048, name: '球鞋' },
                      // { value: 735, name: '防晒霜' }
                    ],
                    emphasis: {
                      itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                      }
                    }
                  }
                ]
              })
            },
    
    async getList(){
                const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
                params: {
                creator: 'kk'
                }
              })
                this.list = res.data.data
    
                //更新图表
                this.myChart.setOption({
                  // 数据项
                  series: [
                    {
                      data: this.list.map(item => ({
                        value: item.price,
                        name: item.name
                      }))
                    }
                  ]
                })
              },
    

工程化开发&脚手架Vue CLI

  • Vue CLI是一个全局命令工具,可以快速搭建一个开发Vue的标准化基础架子(集成了webpack配置

  • 使用步骤:

    • 1.全局安装(一次):npm i @vue/cli -gyarn global add @vue/cli

    • 2.查看Vue版本:vue --version

    • 3.创建项目架子:vue create 项目名(不能有中文)

    • 4.启动项目:npm run serveyarn serve

      • 这个不一定都是serve,要去看package.json
        在这里插入图片描述
  • 项目目录介绍
    在这里插入图片描述

组件化开发&根组件

  • 组件化:一个页面被拆分成一个个组件,每个组件都有自己独立的结构、样式、行为
  • 组件分类:普通组件、根组件
  • 根组件:整个应用最上层的组件,包裹所有普通小组件
    • 三部分组成:
      • template:结构(有且只有一个根元素
      • script:js逻辑
      • style:样式(可支持less,需要装包
        • 1.给style加上lang="less"
        • 2.安装依赖包:npm i less less-loader --saveyarn add less less-loader -D

普通组件的注册

  • 1.局部注册:只能在注册的组件内使用

    • ①创建.vue文件(三个部分

    • ②在使用的组件内导入并注册

      import HmHeader from './components/HmHeader.vue';
      export default {
        components: {
          //组件名:组件对象
          HmHeader: HmHeader
        }
      }
      
  • 使用:当成html标签使用<组件名></组件名>

  • PS:组件名规范:大驼峰命名法

  • 2.全局注册:所有组件内都能使用

    • ①创建.vue文件

    • main.js中进行全局注册

      //导入代码往顶部编写
      import HmButton from './components/HmButton.vue'
      Vue.config.productionTip = false
      
      //进行全局注册
      //Vue.component('组件名', 组件对象)
      Vue.component('HmButton', HmButton)
      

scoped样式冲突

  • 默认情况:写在组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。
    • 全局样式:默认组件中的样式作用到全局
    • 局部样式:可以给组件加上scoped属性,可以让样式只作用于当前组件
  • scoped原理:
  • 1.给当前组件模板的所有元素,都会被添加上一个自定义属性
    • data-v-hash值 区分不同的组件
  • 2.css选择器后面,会自动处理,添加上属性选择器[data-v-hash值]

data是一个函数

  • 一个组件的data选项必须是个函数,保持每个组件实例,维护独立的一份数据对象。
  • 每次创建新的组件实例,都会新执行一次data函数,得到一个新对象。

组件通信

  • 组件通信:组件与组件之间的数据传递

    • 组件的数据是独立的,无法直接访问其他组件的数据
  • 组件关系:

    • 父子关系
    • 非父子关系
  • 组件通信方案
    在这里插入图片描述

  • 父子通信:

    • 1.父组件通过props将数据传递给子组件
      • 父组件给子组件标签,添加属性的方式,传值xxx
      • 子组件通过props进行接收xxx
      • 渲染使用{{ xxx }}
    • 2.子组件利用$emit通知父组件修改更新
      • $emit触发事件,给父组件发送消息通知
      • 父组件监听事件
      • 提供处理函数,形参中获取参数
        在这里插入图片描述
  • 非父子通信 -event bus事件总线

    • 作用:非父子之间进行简易消息传递。复杂场景还是用Vuex

    • EventBus
      在这里插入图片描述

    • provide&inject:跨层级共享数据
      在这里插入图片描述

props详解

  • 定义:组件上注册的一些自定义属性

  • 作用:向子组件传递数据

    • 可以传递任意数量的prop
    • 可以传递任意类型的prop
  • props校验为组件的prop指定验证要求,不符合的控制台会有错误提示

  • 语法:

    • 类型校验:props: {校验的属性名: 类型},
    • 非空校验
    • 默认值
    • 自定义校验
    //完整写法
    props:{
    	校验的属性名: {
    		type: 类型,
    		required: true, //是否必填
    		default: 默认值,
    		validator(value){
    			//自定义校验逻辑
    			return 是否通过校验
    		}
    	}
    }
    
  • prop&data单向数据流,共同点:都可以给组件提供数据

    • data的数据是自己的,可以随便改
    • prop的数据是外部的,不能直接改,要遵循单向数据流
      • 单向数据流:父组件的prop更新,会单向向下流动,影响到子组件,这个数据的流动是单向的
    • 谁的数据谁负责

表单类组件封装&v-model简化代码

  • 表单类组件封装

    • 1.父传子:数据应该是从父组件props传递过来的,v-model拆解绑定数据

    • 2.子传父:监听输入,子传父传值给父组件修改

    • 直白地说,子组件没有办法直接使用v-model,因为数据是父组件的。如果要实现这样的功能,就要把语法糖拆开,相当于用了v-model的原理
      在这里插入图片描述

  • 父组件v-model简化代码,实现父组件与子组件数据双向绑定

    • 1.子组件中:props通过value接收,事件触发input
    • 2.父组件中:v-model给组件直接绑定数据 (:value + @input)
      • 子组件已经配置好,才能使用v-model
        在这里插入图片描述

.sync修饰符

  • 作用:可以实现子组件与父组件的双向绑定,简化代码

  • 特点:prop属性名可以自定义,非固定为value

  • 场景:封装弹框类的基础组件,visible属性true显示false隐藏

  • 本质:就是:属性名@update:属性名合写
    在这里插入图片描述

ref 和 $refs

  • 作用:利用ref$refs可以用于获取dom元素或组件实例
  • 特点:查找范围是当前组件,更精确稳定
    • querySelector查找范围是整个页面
  • 用法:
    • 1.获取dom
      • 目标标签 - 添加ref="xxx"属性
      • 通过this.$refs.xxx获取目标标签
    • 2.获取组件
      • 目标组件 - 添加ref="xxx"属性
      • 通过this.$refs.xxx.组件方法()获取目标组件,就可以调用组件对象里面的方法

Vue异步更新、$nextTick

  • 需求:编辑标题,编辑框自动聚焦
    • 1.点击编辑,显示编辑框
    • 2.让编辑框立刻获取焦点
  • 问题:“显示之后”立刻获取焦点是不能成功的!因为Vue是异步更新DOM(提升性能)
  • $nextTick:等DOM更新后,才会触发执行此方法里的函数体
  • 语法:this.$nextTick(函数体)

自定义指令

  • 自己定义的指令,可以封装一些dom操作,扩展额外功能

  • 语法:

    • 全局注册
    • 局部注册
    • inserted会在指令所在的元素,被插入到页面时触发
      在这里插入图片描述
  • 指令的值

    • 语法:在绑定指令时,可以通过等号的形式为指令绑定具体的参数值
    • 通过binding.value可以拿到指令值,指令值修改会触发update函数
    • update钩子可以监听指令值的变化,进行dom更新操作

封装v-loading指令

  • 场景:在开发过程中,发送请求需要时间,在请求的数据未回来的时候,页面会处于空白状态,这样用户体验不好

  • 需求:封装v-loading指令,实现加载中的效果

  • 分析:

    • 1.本质loading效果就是一个蒙层,盖在了盒子上
    • 2.数据请求中,添加蒙层
    • 3.数据请求完毕,移除蒙层
  • 实现:

    • 1.准备一个loading类,通过伪元素定位,设置宽高,实现蒙层
    • 2.添加移除蒙层,本质只需要添加移除类
    • 3.结合自定义指令的语法进行封装复用
    directives: {
        loading: {
          inserted(el, binding){
            binding.value ? el.classList.add('loading') : el.classList.remove('loading')
          },
          update(el, binding){
            binding.value ? el.classList.add('loading') : el.classList.remove('loading')
          }
        }
      }
    

插槽

  • 作用:让组件内部的一些结构支持自定义

  • 插槽分类:

    • 默认插槽:定制一处结构
    • 具名插槽:定制多处结构
  • 作用域插槽是插槽的一个传参语法

  • 默认插槽:一个定制位置

    • 基本语法:

      • 1.在要定制的结构部分,改用<slot></slot>占位

      • 2.使用组件时,<MyDialog></MyDialog>标签内部,传入结构替换slot

    • 后备内容(默认值):封装组件时,可以在<slot>标签内放置内容,作为默认显示内容

  • 具名插槽:一个组件内有多处结构需要外部传入标签

    • 语法:
      • 1.多个slot使用name属性来区分名字
      • 2.template包裹起来,v-slot: 插槽名来分发标签,v-slot: 插槽名可以简化成#插槽名
    • 一旦插槽取名字,就表明是具名插槽,定向分发
  • 作用域插槽:定义slot的同时,是可以传值的。给插槽上可以绑定数据,将来使用组件时可以用。

    • 场景:封装表格组件

      • 1.父传子,动态渲染表格内容
      • 2.利用默认插槽,定制操作列
      • 3.删除或查看都需要使用当前项的id,属于组件内部的数据,通过作用域插槽传值绑定,进而使用
    • 使用步骤:

      • 1.给slot标签,以添加属性的方式传值
      • 2.所有添加的属性都会被收集到一个对象中
      • 3.在template中,通过#插槽名="obj"接收,默认插槽名是default

单页面应用SPA

  • 页面按需更新,这样开发效率高,性能高,用户体验好
  • 按需更新,首先要明确访问路径和组件的对应关系
    在这里插入图片描述

路由

  • Vue中路由:路径和路由的映射关系

  • VueRouter:修改地址栏路径时,切换显示匹配的组件

    • 使用(5 + 2):
    • 1.下载:vue2下载3.x,vue3下载4.x
      • npm i install vue-router@3.6.5
    • 2.引入:import VueRouter from 'vue-router'
    • 3.安装注册:Vue.use(VueRouter)
    • 4.创建路由对象:const router = new VueRouter()
    • 5.注入,将路由对象注入到new Vue实例中,建立关联
    • 2个核心步骤:
    • ①创建需要的组件(views目录),配置路由规则
    • ②配置导航,配置路由出口(路径匹配的组件显示的位置)
    • PS:route 一条路由规则 { path: 路径, component: 组件 }
    • <router-view></router-view>:路由出口 → 匹配的组件所展示的位置
  • 组件分类更易维护

    • src/views存放页面组件-页面展示-配合路由用
    • src/components存放复用组件-展示数据-常用于复用
  • 快速引入组件:基于@代指src目录,从src目录出发找组件

  • Vue路由 - 重定向

    • 问题:网页打开,url默认是/路径,未匹配到组件显示空白
    • 说明:重定向 —-> 匹配path后,强制跳转path路径
    • 语法:path: 匹配路径, redirect: 重定向到的路径
  • Vue路由 - 404

    • 作用:路径找不到匹配时,给出个提示页面
    • 位置:配在路由最后
    • 语法:path: '*'(任意路径), component: NotFound
  • Vue路由 - 模式设置

    • hash路由(默认):会有#
    • history路由(常用):一旦采用history,地址栏就没有#,需要后台配置访问规则
    • 在路由对象mode里面设置

声明式导航

  • 声明式导航router-link,取代a标签

    • ①能跳转,配置to属性必须指定路径,to不需#

    • ②能高亮,默认会自动添加两个高亮类名

      • router-link-active:模糊匹配,用得多
      • 例如:/find,则/find/xxx、/find/one也能匹配
      • router-link-exact-active:精确匹配
      • 例如:/find,则只有/find能匹配
    • 定制两个高亮类名

      const router = new Router({
      	routes: [...],
      	linkActiveClass: "类名1",
      	linkExactActiveClass: "类名2"
      })
      
  • 声明式导航 - 跳转传参

    • 1.查询参数传参(比较适合传多个参数

      • 语法格式:to="/path?参数名=值"
      • 对应页面组件接收传递过来的值:$route.query.参数名
    • 2.控制路由传参(传单个参数方便

      • ①配置动态路由

        const router = new Router({
        	routes: [
        		...,
        		{
        			path: '/search/:参数名',
        			component: Search
        		}
        	],	
        })
        
      • ②配置导航链接:to="/path/参数值"

      • ③对应页面接收传递过来的值:$route.params.参数名

      • 比如:在配置路由path: '/serach/:words',没有传参数会匹配不到组件,显示空白。如果不传参数也希望匹配,就可以加个可选符?,即path: '/serach/:words?'

编程式导航

  • 编程式导航 - 基本跳转

    • path路径跳转(简易方便)

      this.$router.push('路由路径')
      或
      this.$router.push({
      	path: '路由路径'
      })
      
    • name命名路由跳转(适合path路径长的场景):需要给路由取名字

      {name: '路由名', path: '/xxx', component: xxx}
      this.$router.push{
      	name: '路由名'
      }
      
  • 编程式导航 - 路由传参

    • 1.path路径跳转传参

      • query传参的语法格式:

        this.$router.push('/path?参数名1=值1&参数名2=值2')
        this.$router.push({
        	path: '路径',
        	query: {
        		参数名1: '参数值1',
        		参数名2: '参数值2'
        	}
        })
        
      • 对应页面组件接收传递过来的值:$route.query.参数名

      • 动态路由传参(需要配动态路由)的语法格式:

      • PS:push里面是``,不是引号

        this.$router.push(`/path/参数值`)
        this.$router.push({
        	path: '/路径/参数值',
        })
        
      • 对应页面接收传递过来的值:$route.params.参数名

    • 2.name命名路由跳转传参

      • query传参的语法格式:

        this.$router.push({
        	name: '路径名字',
        	query: {
        		参数名1: '参数值1',
        		参数名2: '参数值2'
        	}
        })
        
      • 对应页面组件接收传递过来的值:$route.query.参数名

      • 动态路由传参(需要配动态路由)的语法格式:

        this.$router.push({
        	name: '路由名',
        	params: {
        		参数名:'参数值',
        	}
        })
        
      • 对应页面接收传递过来的值:$route.params.参数名

组件缓存 keep-alive

  • 内置组件,当它包裹动态组件时,会缓存不活动的组件,而不是销毁它们。
  • 它自身不会渲染成一个DOM元素,也不会出现在父组件链中。
  • 优点:在组件切换过程中,把切换出去的组件保存在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验。
  • 三个属性:
    • :include="组件名数组":只有匹配的组件会被缓存
      • 如果没有配置name,才会去找文件名作为组件名
      • 被缓存的组件多了两个生命周期钩子
        • activated:激活时,组件被看到触发
        • deactivated:失活时,离开页面组件看不见触发
      • 组件缓存后就不会执行组件的created、mounted、destroyed钩子了
    • exclude:任何匹配的组件都不会被缓存
    • max:最多可以缓存多少组件实例,用==LRU算法==(最久没有被访问的)来替换组件

Vuex

  • vuex是一个状态管理工具,状态就是数据,就是一个插件,帮我们管理vue通用的数据(多组件共享的数据

  • 场景:

    • 某个状态在很多个组件来使用(个人信息
    • 多个组件共同维护一份数据(购物车
  • 优势:

    • 共同维护一份数据,数据集中化管理
    • 响应式变化
    • 操作简单,vuex提供了一些辅助函数
  • state状态

    • 1.State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储,在state对象中可以添加我们要共享的数据
    • 2.使用数据:
      • 通过store直接访问(一层一层往下找
        • 模板中:{{ $store.state.xxx }}
        • 组件逻辑中:this.$store.state.xxx
        • js模块中:store.state.xxx
      • 通过辅助函数:mapState能把store中的数据自动映射到组件的计算属性中
        • 导入mapStateimport { mapState } from 'vuex'
        • 数组方式引入state...mapState(['属性'])
        • 展开运算符...映射
  • vuex同样遵循单向数据流,组件中不能直接修改仓库的数据,可以通过mutations来修改数据

    • 通过strict: true可以开启严格模式来检测错误代码
  • mutations:必须是同步的,便于监测数据变化,记录调试

    • 使用:

      • 1.定义mutations对象,对象中存放修改state的方法
      • 2.组件中提交调用mutationsthis.$store.commit('mutations中的方法名')
    • 传参语法

      • 1.提供mutations函数(带参数 - 提交载荷payload

        mutations: {
        	...
        	xxx (state, 参数) {
        		方法逻辑
        	}
        }
        
      • PS:mutations参数有且只能有一个,如果需要多个参数,可以包装成一个对象或数组

      • 2.页面中提交调用mutationsthis.$store.commit('xxx', 参数)

  • mapMutations:把位于mutations中的方法提取出来,映射到组件methods中。相当于把仓库里的数据和方法拿到了当前组件内,就可以直接使用了。

  • actions:处理异步操作

    • 需求:一秒之后,修改statecount

    • 语法:

      • 1.提供actions方法

      • 不能直接操作state,操作state还是需要commit mutation

        actions: {
        	setAsynCount (context, num) {
        		//context 上下文 此处未分模块,可以当成store仓库
        		//setTimeout模拟异步 以后大部分场景是发请求
        		setTimeout (() => {
        			context.commit('方法名', num)
        		}, 1000)
        	}
        }
        
      • 2.页面中dispatch调用:this.$store.dispatch('setAsynCount', 参数)

      • 也有且只能有一个参数

  • mapActions:把位于actions中的方法提取出来,映射到组件methods中。相当于把仓库里的数据和方法拿到了当前组件内,就可以直接使用了。

  • getters:类似于计算属性,需要从state派生出一些状态,这些状态是依赖state的,此时会用到getters

    • 1.定义getters

      getters: {
      	//第一个参数是state
      	//getters函数必须要有返回值,返回的就是getters的值
      	xxx (state) {
      		return xxxx
      	}
      }
      
    • 2.访问getters

      • 通过store{{ $store.getters.xxx }}

      • 通过mapGetters映射

        computed: {
        	...mapGetters(['xxx'])
        }
        {{ xxx }}
        
  • PS:mapMutationsmapActions都是映射方法,而mapStatemapGetters都是映射属性

模块 module

  • 模块 module:由于vuex使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变复杂时,store对象就会可能变得很臃肿。
  • 使用模块中的数据:
    • 1.直接通过模块名访问$store.state.模块名.xxx
    • 2.通过mapState映射
      • 默认根级别的映射mapState(['xxx'])
      • 子模块的映射mapState('模块名', ['xxx'])
        • 需要开启命名空间,在子模块的js文件的export加上namespaced: true
  • 分模块后,getters的函数里state参数指的是子模块的state
  • 默认模块中的mutationactions会被挂载到全局,需要开启命名空间,才会挂载到子模块
    • 调用子模块中的mutation
      • 直接store调用:$store.commit('模块名/xxx', 额外参数)
      • 通过mapMutations映射:
        • 根级别:mapMutations(['xxx'])
        • 子模块:mapMutations('模块名', ['xxx'])
    • context上下文,默认提交的是自己模块mutationactions
  • PS:actions跟这个没区别,只不过是直接调用是:$store.dispatch('模块名/xxx', 额外参数)
  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值