【前端框架】Vue2合集

一、Vue快速上手

1、Vue概念

vue 是一个用于构建用户界面的渐进式框架,由数据驱动

vue 的两种使用方式

  1. vue 核心包开发:局部模块改造
  2. vue 核心包与 vue 插件 工程化开发:整站 开发

2、 创建实例

1、准备容器

<div id="app"></div>

2、导包

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

3、创建Vue实例

const vue = new Vue()

4、指定配置项 => 渲染数据

const vue = new Vue({
    // el:配置选择器
    el: '#app',
    // data:提供数据
    data: {
        msg: 'hello vue',
        h: 'VUE!'
    }
})
<div id="app">
    <h1>{{ h }}</h1>
    {{ msg }}
</div>

3、插值表达式

插值表达式语法:{{ 表达式 }}

利用表达式插值,渲染到页面

<p>{{ title }}</p>

4、响应式特性

数据的响应式处理:数据变化,视图自动更新。数据驱动视图更新

  1. 访问数据: “实例.属性名”
  2. 修改数据: “实例.属性名”= “新值”

二、Vue指令

1、常用指令

指令(Directives)是 Vue 提供的带有 v- 前缀 的 特殊 标签属性

  • 内容渲染指令(v-html、v-text)
  • 条件渲染指令(v-show、v-if、v-else、v-else-if)
  • 事件绑定指令(v-on)
  • 属性绑定指令 (v-bind)
  • 双向绑定指令(v-model)
  • 列表渲染指令(v-for)

2、内容渲染指令

v-text(类似innerText):将 uame 值渲染到 p 标签中,覆盖 p 标签原有内容

<p v-text="uname">hello</p>

v-html(类似 innerHTML):将 intro 值渲染到 p 标签中,能够将HTML标签的样式呈现出来。

<p v-html="intro">hello</p>

3、条件渲染指令

条件判断指令,用来辅助开发者按需控制 DOM 的显示与隐藏。

v-show:(控制元素显示隐藏)切换 display:none 控制显示隐藏。

v-if:(条件渲染)基于条件判断,是否创建 或 移除元素节点。

语法:v-show = “表达式”,v-if = “表达式”。表达式值为 true 显示, false 隐藏。

v-else 和 v-else-if:

  1. 作用:辅助v-if进行判断渲染
  2. 语法:v-else v-else-if=“表达式”
  3. 需要紧接着v-if使用

4、事件绑定指令

<button v-on:事件名="内联语句">按钮</button>
<button v-on:事件名="处理函数">按钮</button>
<button v-on:事件名="处理函数(实参)">按钮</button>

v-on: 简写为 @

(1)内联语句:

<button @click="cnt++">+</button>
<div>{{ cnt }}</div>
<button @click="cnt--">+</button>

(2)处理函数:

事件处理函数写在methods中,methods中的函数内部的this都指向Vue实例

<div id="app">
    <button @click="hd">切换</button>
    <h3 v-show="hide">method函数切换显示和隐藏</h3>
</div>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            hide: true
        },
        methods: {
            hd() {
                this.hide = !this.hide
            }
        }
    })
</script>

(3)调用传参:

如果不传递任何参数,则方法无需加小括号;methods方法中可以直接使用 e 当做事件对象

如果传递了参数,则实参 $event 表示事件对象(固定用法)

<div id="app">
    <div class="box">
        <h3>小黑自动售货机</h3>
        <button @click="fn(5)">可乐5元</button>
    </div>
    <p>银行卡余额:{{ money }}元</p>
</div>
const app = new Vue({
    el: '#app',
    data: {
        money: 100
    },
    methods: {
        fn(i) {
            this.money -= i
        }
    }
})

5、属性绑定指令

动态设置html的标签属性 比如:src、url、title

语法:**v-bind:**属性名=“表达式”,**v-bind:**可以简写成 :

<img :src="img">

6、列表渲染指令

v-for 列表渲染指令,用来基于一个数组来循环渲染一个列表结构。

<p v-for='(item, index) in arr'> </p>

v-for 的语法:

  • item 是数组中的每一项
  • index 是每一项的索引(可以省略)
  • arr 是被遍历的数组
<ul>
    <li v-for="(item, index) in list">{{ index + '--' + item}}</li>
</ul>

v-for中的key:给列表项添加的唯一标识。便于Vue进行列表项的正确排序复用

Vue 的默认行为会尝试原地修改元素(就地复用)

<ul>
  <li v-for="(item, index) in booksList" :key="item.id">
    <span>{{ item.name }}</span>
    <span>{{ item.author }}</span>
    <button @click="del(item.id)">删除</button>
  </li>
</ul>

7、双向绑定指令

1、数据变化 => 视图自动更新

2、视图变化 => 数据自动更新

**语法:**v-model=“变量”

姓名:<input type="text" v-model="username">

v-model绑定其他表单元素:

  • 输入框 input:text => value
  • 文本域 textarea => value
  • 复选框 input:checkbox => checked
  • 单选框 input:radio => checked
  • 下拉菜单 select => value

8、指令修饰符

所谓指令修饰符就是通过.指明一些指令后缀不同的后缀封装了不同的处理操作 (简化代码)

  • @keyup.enter => 当点击enter键的时候才触发
  • v-model.trim => 去除首位空格
  • v-model.number => 转数字
  • @事件名.stop => 阻止冒泡
  • @事件名.prevent => 阻止默认行为
  • @事件名.stop.prevent => 可以连用 即阻止事件冒泡也阻止默认行为

9、v-bind操作class

(1)数组

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

(2)对象

当class动态绑定的是对象时,键就是类名,值就是布尔值,如果值是true,就有这个类,否则没有这个类

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

10、v-bind操作style

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

三、computed计算属性

1、计算属性概述

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

  1. 声明在 computed 配置项中,一个计算属性对应一个函数
  2. 使用起来和普通属性一样使用 {{ 计算属性名 }}

2、计算属性与方法区别

  • computed计算属性:封装了一段对于数据的处理,求得一个结果
  • methods计算属性:给Vue实例提供一个方法,调用以处理业务逻辑

计算属性的优势:

  1. 缓存特性(提升性能):计算属性会对计算出来的结果缓存,再次使用直接读取缓存,依赖项变化了,会自动重新计算并再次缓存

  2. methods没有缓存特性

3、计算属性的完整写法

计算属性默认的简写,只能读取访问,不能 “修改”

四、watch侦听器

1、watch侦听器

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

watch同样声明在跟data同级的配置项中

  1. 简单写法:简单类型数据直接监视
  2. 完整写法:添加额外配置项
data: { 
  words: '苹果',
  obj: {
    words: '苹果'
  }
},

watch: {
  // 该方法会在数据变化时,触发执行
  数据属性名 (newValue, oldValue) {
    一些业务逻辑 或 异步操作。 
  },
  '对象.属性名' (newValue, oldValue) {
    一些业务逻辑 或 异步操作。 
  }
}

2、侦听器完整语法

  1. deep:true 对复杂类型进行深度监听
  2. immdiate:true 初始化 立刻执行一次
data: {
  obj: {
    words: '苹果',
    lang: 'italy'
  },
},

watch: {// watch 完整写法
  对象: {
    deep: true, // 深度监视
    immdiate:true,//立即执行handler函数
    handler (newValue) {
      console.log(newValue)
    }
  }
}

五、生命周期

1、Vue生命周期

生命周期四个阶段:① 创建 ② 挂载 ③ 更新 ④ 销毁

  1. 创建阶段:创建响应式数据
  2. 挂载阶段:渲染模板
  3. 更新阶段:修改数据,更新视图
  4. 销毁阶段:销毁Vue实例

2、Vue生命周期钩子

Vue生命周期过程中,会自动运行一些函数,被称为【生命周期钩子】→ 让开发者可以在【特定阶段】运行自己的代码

六、工程化开发

1、工程化开发和脚手架

  • 核心包传统开发模式:基于html / css / js 文件,直接引入核心包,开发 Vue。
  • 工程化开发模式:基于构建工具(例如:webpack)的环境中开发Vue。

工程化开发模式优点:提高编码效率,比如使用JS新语法、Less/Sass、Typescript等通过webpack都可以编译成浏览器识别的ES3/ES5/CSS等

脚手架Vue CLI: Vue CLI 是Vue官方提供的一个全局命令工具

## 1、全局安装(只需安装一次即可)
vue create project-nameyarn global add @vue/cli
## npm i @vue/cli -g

## 2、查看vue/cli版本
vue --version

## 3、创建项目架子
vue create project-name

## 4、启动项目
yarn serve
## npm run serve

2、项目目录与运行流程

  1. main.js 入口文件
  2. App.vue App根组件
  3. index.html 模板文件

3、组件化开发

组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为。

好处:便于维护,利于复用 → 提升开发效率。

组件分类:普通组件、根组件。

Vue的三部分:

  • template:结构 (有且只能一个根元素)
  • script: js逻辑
  • style: 样式 (可支持less,需要装包)

<template>
  <div class="App">
    <div class="box" @click="fn"></div>
  </div>
</template>

<script>
// 导出的是当前组件的配置项
// 里面可以提供 data(特殊) methods computed watch 生命周期八大钩子
export default {
  created () {
    console.log('我是created')
  },
  methods: {
    fn () {
      alert('你好')
    }
  }
}
</script>

<style lang="less">
/* 
   让style支持less
   1. 给style加上 lang="less"
   2. 安装依赖包 less less-loader
      yarn add less less-loader -D (开发依赖)
*/
.App {
  width: 400px;
  height: 400px;
  background-color: pink;
  .box {只能在注册的组件内使用
    width: 100px;
    height: 100px;
    background-color: skyblue;
  }
}
</style>

4、普通组件的注册使用

1)局部注册

特点:只能在注册的组件内使用

  1. 创建.vue文件(三个组成部分)
  2. 在使用的组件内先导入再注册
  3. 当成html标签使用即可 <组件名></组件名>

组件名规范:必须大驼峰命名法

// 导入需要注册的组件
import 组件对象 from '.vue文件路径'
import HmHeader from './components/HmHeader'

export default {  // 局部注册
  components: {
   '组件名': 组件对象,
    HmHeader:HmHeaer,
    HmHeader
  }
}
2)全局注册

特点:全局注册的组件,在项目的任何组件中都能使用

  1. 创建.vue组件(三个组成部分)
  2. main.js中进行全局注册
  3. 当成HTML标签直接使用
// 导入需要全局注册的组件
import HmButton from './components/HmButton'
Vue.component('HmButton', HmButton)

5、scoped解决样式冲突

  1. 全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响

  2. 局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件

<template>
  <div class="base">
    Base
  </div>
</template>

<script>
export default {

}
</script>

<style scoped>
</style>

scoped原理:

  1. 当前组件内标签都被添加data-v-hash值 的属性
  2. css选择器都被添加 [data-v-hash值] 的属性选择器

6、data是一个函数

一个组件的 data 选项必须是一个函数

目的:保证每个组件实例,维护独立的一份数据对象。每次创建新的组件实例,都会新执行一次data 函数,得到一个新对象。

<script>
export default {
  data: function () {
    return {
      count: 100,
    }
  },
}
</script>

七、组件通信

1、组件通信

1)组件之间如何通信

2)通信解决方案

2、父子通信

1)父子通信
  1. 父组件通过 props 将数据传递给子组件
  2. 子组件利用 $emit 通知父组件修改更新

父传子:

  1. 给子组件以添加属性的方式传值
  2. 子组件内部通过props接收
  3. 模板中直接使用 props接收的值

**子传父:**子组件利用 $emit 通知父组件,进行修改更新

  1. $emit触发事件,给父组件发送消息通知
  2. 父组件监听$emit触发的事件
  3. 提供处理函数,在函数的性参中获取传过来的参数
2)props概述

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

作用:向子组件传递数据

  • 可以 传递 任意数量 的prop
  • 可以 传递 任意类型 的prop
3)props校验

为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示。帮助开发者,快速发现错误。

类型校验:

props: {
  校验的属性名: 类型
},

完整写法:

props: {
  校验的属性名: {
    type: 类型,  // Number String Boolean ...
    required: true, // 是否必填
    default: 默认值, // 默认值
    validator (value) {
      // 自定义校验逻辑
      return 是否通过校验
    }
  }
},
5)props&data、单向数据流
  • data 的数据是自己的 → 随便改
  • prop 的数据是外部的 → 不能直接改,要遵循 单向数据流

单向数据流:父级 props 的数据更新,会向下流动,影响子组件。这个数据流动是单向的

原则:谁的数据谁负责

3、非父子通信

1)event bus 事件总线

1、创建一个都能访问的事件总线 (空Vue实例)

import Vue from 'vue'
const Bus = new Vue()
export default Bus

2、A组件(接受方),监听Bus的 $on事件

created () {
  Bus.$on('sendMsg', (msg) => {
    this.msg = msg
  })
}

3、B组件(发送方),触发Bus的$emit事件

Bus.$emit('sendMsg', '这是一个消息')

2)provide&inject

作用:跨层级共享数据

1、父组件 provide 提供数据

export default {
  provide () {
    return {
       // 普通类型【非响应式】
       color: this.color, 
       // 复杂类型【响应式】
       userInfo: this.userInfo, 
    }
  }
}

2、子、孙组件 inject 获取数据

export default {
  inject: ['color','userInfo'],
  created () {
    console.log(this.color, this.userInfo)
  }
}
  • provide提供的简单类型的数据不是响应式的,复杂类型数据是响应式。(推荐提供复杂类型数据)
  • 子/孙组件通过inject获取的数据,不能在自身组件内修改

八、进阶语法

1、v-model进阶

1)v-model原理

v-model本质上是一个语法糖。例如应用在输入框上,就是value属性 和 input事件 的合写

<input v-model="msg" type="text">

<input :value="msg" @input="msg = $event.target.value" type="text">
  • 数据变,视图跟着变 :value
  • 视图变,数据跟着变 @input

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

2)表单类组件封装

v-model其实就是 :value@input事件的简写

  • 子组件:props通过value接收数据,事件触发 input
  • 父组件:v-model直接绑定数据

子组件

<select :value="value" @change="handleChange">
    <option value="1">yx1</option>
    <option value="2">yx2</option>
</select>
<script>
export default {
  props: ['value'],
  methods: {
    handleChange(e) {
      this.$emit('input', e.target.value)
    }
  }
}
</script>

父组件

<VmolelTest v-model="select"></VmolelTest>

2、.sync修饰符

.sync:可以实现 子组件 与 父组件数据 的 双向绑定

本质:.sync修饰符 就是 :属性名@update:属性名 合写

父组件

//.sync写法
<BaseDialog :visible.sync="isShow" />
--------------------------------------
// 完整写法
<BaseDialog 
  :visible="isShow" 
  @update:visible="isShow = $event" 
/>

子组件

props: {
  visible: Boolean
},

this.$emit('update:visible', false)

3、ref和$refs

利用ref$refs 可以用于 获取 dom 元素 或 组件实例

1、给要获取的盒子添加ref属性

<div ref="yx">我真是伊煊</div>
<button @click="change"></button>

2、通过 $refs 获取 this.\$refs.chartRef 获取

export default {
  methods: {
    change() {
        this.$refs.yx.innerText = '其实我是扑流萤!'
    }
  }
}

只用document.querySelect(‘.box’) 获取的是整个页面中的盒子

4、异步更新 与 $nextTick

Vue 是异步更新DOM (提升性能)

$nextTick等 DOM更新后,才会触发执行此方法里的函数体

语法: this.$nextTick(函数体)

this.$nextTick(() => {
    this.$refs.inp.focus()
})

$nextTick 内的函数体 一定是箭头函数,这样才能让函数内部的this指向Vue实例

九、自定义指令

1、基本语法

自定义指令:封装一些DOM操作,扩展额外的功能

全局注册

//在main.js中
Vue.directive('指令名', {
    "inserted" (el) {
        // 可以对 el 标签,扩展额外功能
        el.focus()
    }
})

局部注册

//在Vue组件的配置项中
directives: {
  "指令名": {
    inserted (el) {
      // 可以对 el 标签,扩展额外功能
      el.focus()
    }
  }
}

在使用指令的时候,一定要先注册再使用,否则会报错

使用指令语法: v-指令名。

<input type="text"  v-focus/>  

注册指令时不用v-前缀,但使用时一定要加v-前缀

2、自定义指令传参

在绑定指令时,可以通过“等号”的形式为指令 绑定 具体的参数值

<div v-color="color">我是内容</div>

通过 binding.value 可以拿到指令值,指令值修改会 触发 update 函数

directives: {
  color: {
    inserted (el, binding) {
      el.style.color = binding.value
    },
    update (el, binding) {
      el.style.color = binding.value
    }
  }
}

十、插槽

1、默认插槽

让组件内部的一些 结构 支持 自定义

  1. 组件内需要定制的结构部分,改用<slot></slot>占位
  2. 使用组件时, <MyDialog></MyDialog>标签内部, 传入结构替换slot
  3. 给插槽传入内容时,可以传入纯文本、html标签、组件

2、后备内容(默认值)

封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)。

  • 外部使用组件时,不传东西,则slot会显示后备内容
  • 外部使用组件时,传东西了,则slot整体会被换掉
<template>
  <div class="dialog-test">
    <slot>我是默认内容</slot>
  </div>
</template>
<template>
  <div id="app">
    <DialogTest>我是自定义内容</DialogTest>
    <DialogTest></DialogTest>
  </div>
</template>

3、具名插槽

一个组件内有多处结构,需要外部传入标签,进行定制

  • 多个slot使用name属性区分名字
  • template配合v-slot:名字来分发对应标签

v-slot的简写: v-slot —> #

<template>
  <div class="dialog-test2">
    <div>name:
      <slot name="name"></slot>
    </div>
  </div>
</template>
<DialogTest2>
    <template #name>伊煊</template>
</DialogTest2>

4、作用域插槽

定义slot 插槽的同时, 是可以传值的。给 插槽 上可以 绑定数据,将来 使用组件时可以用

1、给 slot 标签, 以 添加属性的方式传值

<slot :id="item.id" msg="测试文本"></slot>

2、所有添加的属性, 都会被收集到一个对象中

{ id: 3, msg: '测试文本' }

3、在template中, 通过 #插槽名= "obj" 接收,默认插槽名为 default

<MyTable :list="list">
  <template #default="obj">
    <button @click="del(obj.id)">删除</button>
  </template>
</MyTable>

十一、路由

1、单页应用程序介绍

单页应用程序SPA:是指所有的功能都在一个html页面上实现

网易云音乐 https://music.163.com/

  • 单页应用类网站:系统类网站 / 内部网站 / 文档类网站 / 移动端站点
  • 多页应用类网站:公司官网 / 电商类网站

优点:页面按需更新

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

2、路由的基本使用

路由作用:修改地址栏路径时,切换显示匹配的组件

VueRouter的使用(5+2)

固定5个固定的步骤

1、下载 VueRouter 模块到当前工程,版本3.6.5

yarn add vue-router@3.6.5

2、main.js中引入VueRouter

import VueRouter from 'vue-router'

3、安装注册

Vue.use(VueRouter)

4、创建路由对象

const router = new VueRouter()

5、注入,将路由对象注入到new Vue实例中,建立关联

new Vue({
  render: h => h(App),
  router:router
}).$mount('#app')

两个核心步骤

1、创建需要的组件(views目录),配置路由规则

2、配置导航,配置路由出口(路径匹配的组件显示的位置)

<div class="footer_wrap">
  <a href="#/find">发现音乐</a>
  <a href="#/my">我的音乐</a>
  <a href="#/friend">朋友</a>
</div>
<div class="top">
  <router-view></router-view>
</div>

3、组件的存放目录

.vue文件 本质无区别,分类开来的目的就是为了 更易维护

  1. src/views文件夹:页面组件 - 页面展示 - 配合路由用

  2. src/components文件夹:复用组件 - 展示数据 - 常用于复用

4、路由的封装抽离

拆分模块,利于维护

脚手架环境下 @指代src目录,可以用于快速引入组件

5、声明式导航

1)导航链接

vue-router 提供了一个全局组件 router-link (取代 a 标签)

  • 能跳转,配置 to 属性指定路径(必须) 。本质还是 a 标签 ,to 无需 #
  • 能高亮,默认就会提供高亮类名,可以直接设置高亮样式
<div>
    <div class="footer_wrap">
        <router-link to="/find">发现音乐</router-link>
        <router-link to="/my">我的音乐</router-link>
        <router-link to="/friend">朋友</router-link>
    </div>
    <div class="top">
        <!-- 路由出口 → 匹配的组件所展示的位置 -->
        <router-view></router-view>
    </div>
</div>

实现高亮:

当前点击的链接默认加了两个class的值 router-link-exact-activerouter-link-active

  1. router-link-active:模糊匹配
  2. router-link-exact-active:精确匹配

自定义类名:

用于定制默认的两个类名

const router = new VueRouter({
    routes: [...],
	linkActiveClass: "类名1",
    linkExactActiveClass: "类名2"
})
2)查询参数传参

传递参数:

<router-link to="/path?参数名=值"></router-link>

接受参数:

this.$route.query.参数名
3)动态路由传参

动态路由后面的参数可以随便起名,但要有语义

配置动态路由:

const router = new VueRouter({
    routes: [
        ...,
        { 
        	path: '/search/:words', 
        	component: Search 
        }
	]
})

配置导航链接:

<router-link to="/path/参数值"></router-link>

对应页面组件接受参数:

this.$route.params.参数名

params后面的参数名要和动态路由配置的参数保持一致

4)动态路由参数的可选符

/search/:words 表示,必须要传参数。如果不传参数,也希望匹配,可以加个可选符?

const router = new VueRouter({
  routes: [
 	...,
    { path: '/search/:words?', component: Search }
  ]
})

8、Vue路由

1)重定向

网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空白

重定向 → 匹配 / 后, 强制跳转 /home 路径

{ path: 匹配路径, redirect: 重定向到的路径 },
// 比如:
{ path:'/' ,redirect:'/home' }
2)404

当路径找不到匹配时,给个提示页面。一般都配置在其他路由规则的最后面。

import NotFind from '@/views/NotFind'

const router = new VueRouter({
  routes: [
    ...
    { path: '*', component: NotFind } // 最后一个
  ]
})
3)路由模式设置

路由的路径看起来不自然, 有个#

  • hash路由(默认) 例如: http://localhost:8080/#/home
  • history路由(常用) 例如: http://localhost:8080/home

以后上线需要服务器端支持,开发环境webpack给规避掉了history模式的问题

const router = new VueRouter({
    mode:'history', //默认是hash
    routes:[]
})

9、编程式导航

1)path路径跳转

不传参:

// 简单写法
this.$router.push('路由路径')

// 完整写法
this.$router.push({
    path: '路由路径'
})

传参:

// 1、query传参
// 简单写法
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
// 完整写法
this.$router.push({
    path: '/路径',
    query: {
        参数名1: '参数值1',
        参数名2: '参数值2'
    }
})

// 2、动态路由传参
// 简单写法
this.$router.push('/路径/参数值')
// 完整写法
this.$router.push({
  path: '/路径/参数值'
})
2)name命名路由

适合 path 路径长的场景

不传参:

路由规则,必须配置name配置项

{ name: '路由名', path: '/path/xxx', component: XXX },

通过name来进行跳转

this.$router.push({
    name: '路由名'
})

传参:

// 1、query传参
this.$router.push({
    name: '路由名字',
    query: {
        参数名1: '参数值1',
        参数名2: '参数值2'
    }
})

// 2、动态路由传参
this.$router.push({
    name: '路由名字',
    params: {
        参数名: '参数值',
    }
})

10、二级路由

const router = new VueRouter({
    routes: [
        {
            path: '/',
            component: Layout,
            children:[
                //children中的配置项 跟一级路由中的配置项一模一样 
                { path:'xxxx', component:xxxx.vue },
                { path:'xxxx', component:xxxx.vue },
            ]
        }
    ]
})

这些二级路由对应的组件渲染到哪个一级路由下,children就配置到哪个路由下边

配置了嵌套路由,一定配置对应的路由出口,否则不会渲染出对应的组件

11、组件缓存

keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。

<template>
	<div class="h5-wrapper">
    	<keep-alive>
        	<router-view></router-view>
    	</keep-alive>
    </div>
</template>

keep-alive的三个属性:

  1. include:组件名数组,只有匹配的组件会被缓存
  2. exclude:组件名数组,任何匹配的组件都不会被缓存
  3. max:最多可以缓存多少组件实例

keep-alive的两个生命周期钩子:

  1. activated 当组件被激活(使用)的时候触发 → 进入这个页面的时候触发
  2. deactivated 当组件不被使用的时候触发 → 离开这个页面的时候触发

十二、代码规范

1、VueCli 自定义创建项目

1、安装脚手架

npm i @vue/cli -g

2、创建项目

vue create demo

3、选自定义

4、选择配置

5、选择vue的版本

6、选择是否使用history模式

7、选择css预处理

8、选择eslint的风格

9、选择校验的时机

10、选择配置文件的生成方式

11、不保存预设

image-20230812214636401

2、ESlint代码规范及手动修复

ESLint:是一个代码检查工具,用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)。在创建项目时,我们使用的是 JavaScript Standard Style 代码风格的规则。

根据错误提示来一项一项手动修正。

如果你不认识命令行中的语法报错是什么意思,你可以根据错误代码去 ESLint 规则列表中查找其具体含义。

打开 ESLint 规则表,使用页面搜索(Ctrl + F)这个代码,查找对该规则的一个释义。

3、通过eslint插件来实现自动修正

  1. eslint会自动高亮错误显示
  2. 通过配置,eslint会自动帮助我们修复错误

十三、Vuex

1、Vuex 概述

Vuex 是一个 Vue 的 状态管理工具,状态就是数据。

Vuex 是一个插件,可以帮我们管理 Vue 通用的数据 (多组件共享的数据)

优点:

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

2、Vuex的使用

1、安装vuex

yarn add vuex@3
## npm i vuex@3

2、新建 store/index.js 专门存放 vuex

为了维护项目目录的整洁,在src目录下新建一个store目录其下放置一个index.js文件。

3、创建仓库 store/index.js

// 导入 vue
import Vue from 'vue'

// 导入 vuex
import Vuex from 'vuex'

// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)

// 创建仓库 store
const store = new Vuex.Store()

// 导出仓库
export default store

4、在 main.js 中导入挂载到 Vue 实例上

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

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store
}).$mount('#app')

3、state 状态

State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储。

打开项目中的store.js文件,在state对象中可以添加我们要共享的数据。

// 创建仓库 store
const store = new Vuex.Store({
    // state 状态, 即数据, 类似于vue组件中的data,
    // 区别:
    // 1.data 是组件自己的数据, 
    // 2.state 中的数据整个vue项目的组件都能访问到
    state: {
        count: 101
    }
})

访问Vuex中的数据

1、模板中使用

<h1>state的数据 - {{ $store.state.count }}</h1>

2、组件逻辑中使用

this.$store.state.xxx

3、js文件中使用

//main.js

import store from "@/store"

console.log(store.state.count)

4、提供计算属性

<h1>state的数据 - {{ count }}</h1>
// 把state中数据,定义在组件内的计算属性中
computed: {
    count () {
    	return this.$store.state.count
    }
}

4、辅助函数mapState

mapState是辅助函数,帮助我们把store中的数据映射到 组件的计算属性中, 它属于一种方便的用法

1、导入mapState (mapState是vuex中的一个函数)

import { mapState } from 'vuex'

2、采用数组形式引入state属性

mapState(['count']) 

上面代码的最终得到的是 类似于

count () {
 return this.$store.state.count
}

3、利用展开运算符将导出的状态映射给计算属性

computed: {
    ...mapState(['count'])
}
 <div> state的数据:{{ count }}</div>

5、严格模式和Vuex的单项数据流

明确 vuex 同样遵循单向数据流,组件中不能直接修改仓库的数据

通过 strict: true 可以开启严格模式,开启严格模式后,直接修改state中的值会报错。

state数据的修改只能通过mutations,并且mutations必须是同步的

6、mutations

1)mutations

mutations是一个对象,对象中存放修改state的方法。mutations必须是同步的。

1、定义mutations

const store  = new Vuex.Store({
    // 定义mutations
    mutations: {

    }
})

2、组件中提交 mutations

this.$store.commit('addCount')
2)带参数的 mutations

1、定义mutations(带参数)

const store  = new Vuex.Store({
    addCount (state, count) {
        state.count = count
    }
})

2、组件中提交 mutations

this.$store.commit('addCount', 10)

提交的参数只能是一个,如果有多个参数要传,可以传递一个对象

this.$store.commit('addCount', {
    count: 10
})
3)mapMutations

mapMutations类似于mapState,把位于mutations中的方法提取了出来

import  { mapMutations } from 'vuex'
methods: {
    ...mapMutations(['addCount'])
}

7、actions

1)actions

state是存放数据的,mutations是同步更新数据 (便于监测数据的变化,更新视图等,方便于调试工具查看变化)

actions则负责进行异步操作

1、

mutations: {
    changeCount (state, newCount) {
        state.count = newCount
    }
}

actions: {
    setAsyncCount (context, num) {
        // 一秒后, 给一个数, 去修改 num
        setTimeout(() => {
            context.commit('changeCount', num)
        }, 1000)
    }
}

2、组件中通过dispatch调用

setAsyncCount () {
    this.$store.dispatch('setAsyncCount', 666)
}

2)mapActions

mapActions 是把位于 actions中的方法提取了出来,映射到组件methods中

import { mapActions } from 'vuex'
methods: {
   ...mapActions(['changeCountAction'])
}

8、getters

1)getters

除了state之外,有时我们还需要从state中筛选出符合条件的一些数据(类似于computed计算属性),这些数据是依赖state的,此时会用到getters

1、定义getters

getters: {
	// getters函数的第一个参数是 state
	// 必须要有返回值
	filterList:  state => state.list.filter(item => item > 5)
}

2、使用getters

<div>{{ $store.getters.filterList }}</div>
2)mapGetters
computed: {
    ...mapGetters(['filterList'])
}
 <div>{{ filterList }}</div>

9、module模块化

1)module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护

1、准备user模块 modules/user.js

const state = {
  userInfo: {
    name: 'zs',
    age: 18
  }
}

const mutations = {}

const actions = {}

const getters = {}

export default {
  state,
  mutations,
  actions,
  getters
}

2、在store/index.js文件中的modules配置项中,注册模块

import user from './modules/user'

const store = new Vuex.Store({
    modules:{
        user
    }
})

数据的访问:

this.$store.state.模块名.xxx
2)state模块化

尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的 state 中,属性名就是模块名

  1. 直接通过模块名访问 $store.state.模块名.xxx
  2. 通过 mapState 映射:
    1. 默认根级别的映射 mapState([ 'xxx' ])
    2. 子模块的映射 :mapState('模块名', ['xxx']) (需要开启命名空间namespaced:true
export default {
    namespaced: true,
    ...
}
3)getters模块化
  1. 直接通过模块名访问 $store.getters['模块名/xxx ']
  2. 通过 mapGetters 映射
    1. 默认根级别的映射 mapGetters([ 'xxx' ])
    2. 子模块的映射 mapGetters('模块名', ['xxx']) (需要开启命名空间)
4)mutations模块化
  1. 直接通过 store 调用 $store.commit('模块名/xxx ', 额外参数)
  2. 通过 mapMutations 映射
    1. 默认根级别的映射 mapMutations([ 'xxx' ])
    2. 子模块的映射 mapMutations('模块名', ['xxx'])(需要开启命名空间)
5)actions模块化
  1. 直接通过 store 调用 $store.dispatch('模块名/xxx ', 额外参数)
  2. 通过 mapActions 映射
    1. 默认根级别的映射 mapActions([ 'xxx' ])
    2. 子模块的映射 mapActions('模块名', ['xxx']) (需要开启命名空间)

10、补:json-server

json-server用于模拟后端接口服务环境

1、安装全局工具 json-server (全局工具仅需要安装一次)

yarn global add json-server
npm i json-server -g

2、代码根目录新建一个 db 目录

3、将资料 index.json 移入 db 目录

4、进入 db 目录,执行命令,启动后端接口服务 (使用–watch 参数 可以实时监听 json 文件的修改)

json-server  --watch  index.json

十四、打包优化

1、publicPath

默认情况下,需要放到服务器根目录打开,如果希望双击运行,需要配置 publicPath 配成相对路径

module.exports = {
  // 设置获取.js,.css文件时,是以相对地址为基准的。
  // https://cli.vuejs.org/zh/config/#publicpath
  publicPath: './'
}

2、路由懒加载

当打包构建应用时,Javascript 包会变得非常大影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

const ProDetail = () => import('@/views/prodetail')
const Pay = () => import('@/views/pay')
const MyOrder = () => import('@/views/myorder')

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

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

相关文章

腾讯云把向量数据库“卷”到哪一步了?

“不是我不明白&#xff0c;这世界变化快”&#xff0c;崔健在20世纪写下的这句歌词&#xff0c;放在刚刚过去的2023年&#xff0c;也同样适用。技术风向的变化之快&#xff0c;让不少人感到惊讶&#xff0c;向量数据库这一年的潮起潮落&#xff0c;就是一个典型的例子。 2023年…

文本编码转换:如何从UTF8到ANSI的批量处理技巧

在处理文本文件时&#xff0c;经常会遇到不同编码格式的问题。不同的编码会导致文件在打开或显示时出现乱码。UTF-8和ANSI是两种常见的编码格式。现在一起来看“办公提效工具”如何从UTF-8批量转换到ANSI编码的操作。 文本编码UTF-8未修改前的截图展示。 批量转换ANSI编码的方…

电子学会C/C++编程等级考试2023年09月(五级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:红与黑 有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。 时间限制:1000 内存限制:65536 输入 包括多…

Codeforces Round 779 (Div. 2) D2. 388535(思维题 二进制性质/trie树上最大最小异或)

题目 t(t<1e5)组样例&#xff0c;每次给定l,r(0<l<r<2^17) 和r-l1个数ai&#xff0c;新序列是被[l,r]这些数异或上同一个x得到的&#xff0c; 求出x&#xff0c;有多个输出任意一个即可 思路来源 官方题解 洛谷题解 Educational Codeforces Round 157 (Rated…

MetaGPT学习笔记 - task1task2

章节&#xff1a;task1&task2 一.github地址&#xff1a;github.com/geekan/MetaGPT 二.MetaGPT: 多智能体框架​ 使 GPT 以软件公司的形式工作&#xff0c;协作处理更复杂的任务 MetaGPT输入一句话的老板需求&#xff0c;输出用户故事 / 竞品分析 / 需求 / 数据结构 / A…

流星全自动网页生成系统重构版源码

流星全自动网页生成系统重构版源码分享&#xff0c;所有模板经过精心审核与修改&#xff0c;完美兼容小屏手机大屏手机&#xff0c;以及各种平板端、电脑端和360浏览器、谷歌浏览器、火狐浏览器等等各大浏览器显示。 为用户使用方便考虑&#xff0c;全自动网页制作系统无需繁琐…

分布式任务调度平台XXL-JOB使用(二)

说明&#xff1a;之前总结过在CentOS系统里使用XXL-JOB。但在代码开发阶段&#xff0c;我们有时需要在本地环境测试定时任务代码&#xff0c;本文介绍如何在Windows系统使用XXL-JOB。 下载 &#xff08;1&#xff09;下载代码&#xff0c;解压打开 首先&#xff0c;去Github…

新手入门Java数组排序及二维数组(有练习)

第七章 二维数组 课前回顾 1.数组的定义方式都有哪几种 数据类型[] 数组名; 数组名 new 数据类型[数组的长度];数据类型[] 数组名 new 数据类型[数组的长度];数据类型[] 数组名 {数组的元素1,数组的元素2,...数组的元素n};//只能在定义数组时直接赋值的时候使用数据类型[…

HTML--CSS--图片和背景样式

图片样式 图片大小 最基本的应该就是对大小的管理 width:像素值; 宽度 height:像素值; 高度 <!DOCTYPE html> <html> <head> <title>这是一个标题</title><meta charset"utf-8"/><style>img{width: 300px;height: 300px…

从零开始的OpenGL光栅化渲染器构建2-冯式光照

冯式光照的构成 冯式光照模型(Phong Lighting Model)的主要结构由三个分量组成&#xff1a;环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。 环境光 把环境光照添加到场景里非常简单。我们用光的颜色乘以一个很小的常量环境因子&#xff0c;再乘以物体的颜色&#xf…

【矩阵快速幂】封装类及测试用例及样例

作者推荐 视频算法专题 通俗的说&#xff0c;就是矩阵的乘方。 封装类 核心代码 class CMat { public:// 矩阵乘法static vector<vector<long long>> multiply(const vector<vector<long long>>& a, const vector<vector<long long>…

模拟器安装XPosed框架教程

Xposed框架下载&#xff08;搞不懂就先看完本篇教程再下载&#xff09; 99%的情况只需要下载里面的XPosed鸭就行了 安卓8及以下XPosed框架 - 多开鸭模拟器安装XPosed框架图文视频教程 关于本站XPosed框架的说明 XPosed框架(即XP框架)&#xff0c;由rovo89开发。适用于安卓7以…

任务6:启动Hadoop集群并测试

任务描述 知识点&#xff1a; 掌握Hadoop集群的启动 重 点&#xff1a; Hadoop集群的格式化流程Hadoop集群的启动流程 内 容&#xff1a; 格式化Hadoop集群启动测试Hadoop集群 任务指导 启动Hadoop集群并测试&#xff0c;过程如下&#xff1a; 初始化HDFS&#xff1…

C++面试宝典第19题:最长公共前缀

题目 编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串""。说明:所有输入只包含小写字母a-z。 示例1: 输入: ["flower", "flow", "flight"]输出: "fl" 示例2: 输入: ["dog",…

指针面试题详解

文章目录 指针笔试题解析笔试题1笔试题2笔试题3笔试题4笔试题5笔试题6笔试题7笔试题8 总结 指针笔试题解析 数组名是首元素地址,两种情况除外: 1.sizeof(数组名) , 这是这是计算整个数组的大小,单位是字节; 2.&数组名 , 得出的是整个数组的地址; 笔试题1 #include<st…

学习Vue配置代理总结

今天学习了Vue的配置代理&#xff0c;当我们想要向服务器取回来数据时就先要向服务器发送请求&#xff0c;但前端发送请求的方式也有很多种&#xff0c;首先是发送请求的鼻祖JS的XMLHttpRequest&#xff08;xhr&#xff09;&#xff0c;它操作起来相对麻烦&#xff0c;开发中也…

基于STM32的CMT液晶屏控制器驱动程序设计与优化

本文以STM32微控制器为基础&#xff0c;设计并优化了一个用于控制CMT液晶屏的驱动程序。在设计过程中&#xff0c;我们首先介绍了液晶屏的基本工作原理&#xff0c;包括CMT液晶屏的结构和信号传输机制。然后&#xff0c;我们详细讨论了STM32微控制器的GPIO、SPI和DMA模块的特性…

基于RTOS(实时操作系统)的CMT液晶屏控制器驱动程序开发与实现

RTOS&#xff08;实时操作系统&#xff09;提供了一种有效的方式来管理和调度多任务系统&#xff0c;对于液晶屏控制器的驱动程序开发来说&#xff0c;RTOS能够提供良好的实时性和可靠性。本文以RTOS为基础&#xff0c;设计并实现了一个用于控制CMT液晶屏的驱动程序。在设计过程…

微信小程序-----WXML模板语法之数据绑定与事件绑定

目录 前言 一、数据绑定 1.Mustache语法 2.Mustache 语法的应用场景 &#xff08;1&#xff09;绑定内容 &#xff08;2&#xff09;绑定属性 &#xff08;3&#xff09;运算&#xff08;三元运算、算术运算等) 二、事件绑定 1.事件 &#xff08;1&#xff09;什么是…

Java安装(可多版本共存)及IIntelliJ IDEA环境搭建汉化(保姆级教程!)

编程如画&#xff0c;我是panda&#xff01; 这次给大家出一期JAVA安装以及IIntelliJ IDEA的安装教程 IIntelliJ IDEA分为社区版和专业版&#xff0c;两版的教程都有&#xff0c;小伙伴们根据需要自行选择使用 并且我会讲解一台计算机中多个版本JAVA JDK配置安装 前言 我最早接…