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', 额外参数)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/439294.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony教程指南—ArkUI中组件、通用、动画、全局方法的集合

介绍 本示例为ArkUI中组件、通用、动画、全局方法的集合。 本示例使用 Tabs容器组件搭建整体应用框架&#xff0c;每个 TabContent内容视图 使用 div容器组件 嵌套布局&#xff0c;在每个 div 中使用 循环渲染 加载此分类下分类导航数据&#xff0c;底部导航菜单使用 TabCont…

gradio 摄像头视频流获取

参考&#xff1a;https://github.com/gradio-app/gradio/issues/1490 版本&#xff1a;gradio 4.16.0 gradio_client 0.8.1 import gradio as grgr.Interface(lambda x: x, gr.Image(sourceswebcam, streamingTrue), "image", liveTrue).launch()

【Linux】第一个小程序--进度条

这篇博客要综合利用以前的知识&#xff0c;来实现一个进度条程序~ 目录 换行&回车 缓冲区 实现简单的倒计时 实现进度条 version1 version2 在开始写这个小程序之前&#xff0c;我们先学习一些预备知识&#xff1a; 换行&回车 缓冲区 在我们运行这个程序时&…

堆和堆排序

堆排序是一种与插入排序和并归排序十分不同的算法。 优先级队列 Priority Queue 优先级队列是类似于常规队列或堆栈数据结构的抽象数据类型&#xff08;ADT&#xff09;。优先级队列中的每个元素都有一个相关联的优先级key。在优先级队列中&#xff0c;高优先级的元素优先于…

“2024杭州智慧城市及安防展会”将于4月在杭州博览中心盛大召开

2024杭州国际智慧城市及安防展览会&#xff0c;将于4月24日在杭州国际博览中心盛大开幕。这场备受瞩目的盛会&#xff0c;不仅汇集了全球智慧城市与安防领域的顶尖企业&#xff0c;更是展示最新技术、交流创新理念的重要平台。近日&#xff0c;从组委会传来消息&#xff0c;展会…

电脑开机黑屏解决方案,让我来告诉你

在使用电脑的日常操作中&#xff0c;遇到电脑开机后却只看到一片黑屏可能是一种相当令人困扰的情况。这种问题可能出现在不同的电脑和操作系统中&#xff0c;给用户带来了一定的困扰。在本文中&#xff0c;我们将深入探讨电脑开机黑屏的可能原因以及解决方法&#xff0c;帮助您…

解决方案:Python画图汉字丢失显示小方块

解决方案&#xff1a; linux python解决中文字体 - jingsupo - 博客园 (cnblogs.com) 在找字体缓存文件的时候我找了一会儿&#xff0c;我的路径是这里&#xff1a; 做了所有更改之后&#xff0c;最后一定要把缓存文件删掉&#xff0c;不然还是会报同样的错误的。 这里再贴一…

挑花眼?这样选Six Sigma咨询公司,轻松又靠谱

近年来&#xff0c;市场上涌现出众多的Six Sigma咨询公司&#xff0c;它们各自标榜着专业、高效、经验丰富等标签&#xff0c;让人眼花缭乱&#xff0c;难以抉择。面对这样的情境&#xff0c;企业或个人在选择合作伙伴时难免会感到头大。那么&#xff0c;如何在众多选项中挑选出…

聊一聊ThreadLocal的原理?

1.ThreadLocal创建方式 ThreadLocal<String> threadlocal1 new ThreadLocal(); ThreadLocal<String> threadlocal2 new ThreadLocal(); ThreadLocal<String> threadlocal3 new ThreadLocal(); 2.首先介绍一下&#xff0c;ThreadLocal的原理&#xff1a; 如…

易点易动固定资产管理系统如何为企业固定资产管理保驾护航

固定资产作为企业重要的资产组成部分,它直接影响企业的资金流动和经营发展。然而在传统的管理模式下,固定资产管理效率低下、盲区众多,资产利用率和价值体现不佳。易点易动智能化固定资产管理系统应运而生,为企业固定资产管理保驾护航,帮助企业实现资产高效管控、规避经营风险。…

CubeMX使用教程(2)——点亮LED

在上一章&#xff0c;我们完成了CubeMX的环境配置&#xff0c;这一章我们通过CubeMX来完成点亮LED的工作。 通过LED原理图可知&#xff0c;如果我们要点亮LD1&#xff08;第一个灯&#xff09;&#xff0c;它对应开发板的PC8端口&#xff0c;因此我们应该在CubeMX中将PC8配置为…

『 Linux 』Process Control进程控制(万字)

文章目录 &#x1f996; 前言&#x1f996; fork()函数调用失败原因&#x1f996; 进程终止&#x1f4a5; 进程退出码&#x1f4a5; 进程正常退出 &#x1f996; 进程等待&#x1f4a5; 僵尸进程&#x1f4a5; 如何解决僵尸进程的内存泄漏问题&#x1f4a5; wait( )/waitpid( )…

高中数学:初等函数之幂函数

1、定义 注意&#xff1a;x项系数&#xff0c;只能是1&#xff01; 例题&#xff1a; 2、常见幂函数图像 3、分数指数幂 x定义域&#xff1a;分母为偶数时&#xff0c;如&#xff1a;2、4、6等&#xff0c;则x≥0 x≥0时 4、画草图 步骤&#xff1a; 1、利用结论画出第…

2024最新图标设计趋势!附超好用的图标工具清单

图标&#xff0c;在界面设计中的作用不容小觑。正所谓浓缩的就是精华&#xff0c;一个小小的图标&#xff0c;却有着高效传递信息、美化界面排版、提升用户体验的巨大能力。 既然图标如此重要&#xff0c;了解图标设计趋势对设计师来说几乎是必须要做的事&#xff0c;它可以让…

字符串索引错误解决方案

字符串索引错误通常是由于尝试访问字符串中不存在的索引位置而引起的。我在Python编译中&#xff0c;字符串是一个不可变的序列&#xff0c;可以通过索引访问其中的字符。如果尝试访问超出字符串长度范围的索引位置&#xff0c;将引发IndexError异常。所以下面的问题如果遇到了…

阿里云k8s内OSS报错UnKnownHost。

这个问题就是链接不上oss属于网络问题&#xff1a; 1.排查服务器 在服务器&#xff08;ecs&#xff09;上直接ping oss地址看是否能够通。 不通就要修改dns和hosts&#xff08;这个不说&#xff0c;自己网上查&#xff09; 2.排查容器 进去ping一下你的容器是否能访问到oss…

新能源车高压线束更换VR虚拟互动教学保障了培训安全可控

随着新能源汽车市场的快速发展&#xff0c;对于新能源汽车检修人才的需求也日益增长。然而&#xff0c;传统的培训模式往往存在一些限制&#xff0c;如培训周期长、成本高、实践机会少等。为了解决这些问题&#xff0c;新能源车检修VR互动培训应运而生&#xff0c;成为一种创新…

电脑怎么强制关机?让电脑不再“任性”!

在使用电脑的过程中&#xff0c;有时可能会遇到程序无响应、系统崩溃或遭遇恶意软件攻击等情况&#xff0c;这时就需要我们采取紧急措施&#xff0c;强制关闭电脑。强制关机虽然是一种非常手段&#xff0c;但在必要时能够保护电脑硬件和数据安全。本文将为您介绍电脑怎么强制关…

智慧视频终端解决方案

依托富瀚微智慧视频SOC&#xff0c;提供以视频为核心的智能产品及解决方案

【数据结构与算法】二分查找题解(二)

这里写目录标题 一、81. 搜索旋转排序数组 II二、167. 两数之和 II - 输入有序数组三、441. 排列硬币四、374. 猜数字大小五、367. 有效的完全平方数 一、81. 搜索旋转排序数组 II 中等 已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递…