VUE2--22.11.23

VUE2

一、Vue.js devtools

https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd/related

直接添加到谷歌浏览器就行

在这里插入图片描述

打开扩展程序,点击详情按钮

在这里插入图片描述

在这里插入图片描述

二、Vue简介

1、什么是Vue

官方给出的概念: Vue(读音/vju:/,类似于view)是一套用于构建用户界面的前端框架

1.构建用户界面

  • 用vue往html页面中填充数据,非常的方便

2.框架

  • 框架是一套现成的解决方案,程序员只能遵守框架的规范,去编写自己的业务功能!
  • 要学习vue,就是在学习vue框架中规定的用法!
  • vue的指令、组件(是对UI结构的复用)﹒路由、Vuex、vue组件库。

2、Vue的特性

主要体现在两方面:

  • 数据驱动视图

  • 双向数据绑定

1.数据驱动视图

在这里插入图片描述

2.双向数据绑定

在这里插入图片描述

在网页中,form表单负责采集数据,Ajax负责提交数据。
  • js数据的变化,会被自动渲染到页面上
  • 页面上表单采集的数据发生变化的时候,会被vue自动获取到,并更新到js数据中

3.MVVM

在这里插入图片描述
在这里插入图片描述
注意:数据驱动视图和双向数据绑定的底层原理是MVM (Mode数据源、View视图、ViewModel就是vue的实例)

三、Vue的基本使用

1、基本使用步骤

在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<script src="./lib/vue@2.7.13.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<!-- 希望 vue 控制这个div,帮助我们把数据填充到div内部 -->
		<div id="app">
			{{username}}
		</div>
	</body>
	<script type="text/javascript">
		//创建 Vue 的实例对象
		const vm = new Vue({
			//el 属性是固定的写法,表示当前 vm 实例要控制页面上的那个区域,接收的值是一个选择器
			el: '#app',
			//data 对象就是要渲染到页面上的数据
			data: {
				username: '坏蛋阿土'
			}
		})
	</script>
</html>

MVVM

在这里插入图片描述

四、Vue的指令与过滤器

1、什么是指令

指令(Directives)是vue为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构

vue中的指令按照不同的用途可以分为如下6大类:

  • ①内容渲染指令
  • ②属性绑定指令
  • ③事件绑定指令
  • ④双向绑定指令
  • ⑤条件渲染指令
  • ⑥列表渲染指令

注意:指令是vue开发中最基础、最常用、最简单的知识点。

2、内容渲染指令

内容渲染指令用来辅助开发者渲染DOM元素的文本内容。常用的内容渲染指令有如下3个:

  • v-text
  • {{}}
  • v-html

1.v-text

v-text指令的缺点是:会覆盖元素内部原有的内容

在这里插入图片描述

2.{{}}

在这里插入图片描述

3.v-html

在这里插入图片描述

3、属性绑定指令

插值表达式只能用在元素的内容节点中,不能用在元素的属性节点中!

在vue中,可以使用v-bind:指令,为元素的属性动态绑定值

  • 简写是英文的 :

  • 在使用v-bind属性绑定期间,如果绑定内容需要进行动态拼接,则字符串的外面应该包裹单引号

<div :tit1e=" 'id' + index">这是一个 div</div>

id1 id2 id3
index是一个变量


在这里插入图片描述

4、事件绑定指令

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

在methods中定义事件的处理函数

在这里插入图片描述

在这里插入图片描述

  • methods中定义的方法中可以通过this访问到data中定义的数据 , 其中 this===vm
  • 在绑定事件处理函数的时候,可以使用()传递参数
  • 事件绑定简写 @
  • vue提供了内置变量,名字叫做$event,它就是原生DOM的事件对象e,在需要使用事件对象但是函数又需要传参的时候使用

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

如果同时需要传参,那就使用$event

在这里插入图片描述

在这里插入图片描述


事件修饰符
在这里插入图片描述
按键修饰符

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

5、双向绑定指令

在这里插入图片描述
v-bind 与 v-model区别:

在这里插入图片描述

在这里插入图片描述

v-model指令的修饰符

在这里插入图片描述

oninput 当input的value值发生变化时就会触发,(与onchange的区别是不用等到失去焦点就可以触发了)

6、条件渲染指令

在这里插入图片描述

1.v-show的原理是:动态为元素添加或移除display: none 样式,来实现元素的显示和隐藏

  • 如果要频繁的切换元素的显示状态,用 v-show 性能会更好

2.v-if的原理是:每次动态创建或移除元素,实现元素的显示和隐藏

  • 如果刚进入页面的时候,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时 v-if 性能更好

疑问:vue 的话会先编译后执行

在这里插入图片描述
在这里插入图片描述
type 在 data 中

7、列表渲染指令

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

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述在这里插入图片描述
删除的时候可以用索引


注意事项:
1.
在这里插入图片描述
label for id得动态生成,要不然一直是第一个

2.v-model 内部会去判断 input 的 type,从而确定要把数据渲染给 text 还是 checkbox

3.数组中根据条件删除

在这里插入图片描述

在这里插入图片描述

8、过滤器 Filter (VUE3就没有了)

在这里插入图片描述

  • 1.要定义到filters节点下,本质是一个函数
  • 2.在过滤器函数中,一定要有return值
  • 3.在过滤器的形参中,可以获取到“管道符"前面待处理的那个值
  • 4.如果全局过滤器和私有过滤器名字一致,此时按照"就近原则",调用的是"私有过滤器”

在这里插入图片描述

  • 1.要定义到filters节点下,本质是一个函数
  • 2.在过滤器函数中,一定要有return值
  • 3.在过滤器的形参中,就可以获取到"管道符"前面待处理的那个值

9、私有过滤器和全局过滤器

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

10、使用过滤器格式化时间

在这里插入图片描述

使用Day.js对时间进行格式化处理

10、连续使用多个过滤器及传参

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


在这里插入图片描述

五、Vue侦听器

1、什么是 watch 侦听器

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

监听用户名是否变化

在这里插入图片描述

2、watch 侦听器的格式及immediate选项

1.方法格式的侦听器

  • 缺点1:在刚进入页面的时候,无法自动触发一次
  • 缺点2:如果侦听的是一个对象,如果对象中的属性发生了变化,不会触发侦听器

2.对象格式的侦听器

  • 好处1:可以通过immlediate选项,让侦听器自动触发一次
  • 好处2:可以通过deep选项,让侦听器深度监听对象中每个属性的变化

在这里插入图片描述

3、深度侦听 deep选项

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述

在这里插入图片描述

六、计算属性

1、什么是计算属性

在这里插入图片描述

在这里插入图片描述

定义的时候是一个方法,用的时候就当成VM的一个属性去用就好了

特点:

  • 1.定义的时候,要被定义为“方法"
  • ⒉.在使用计算属性的时候,当普通的属性使用即可

好处:

  • 1.实现了代码的复用

  • 2.只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值

七、Axios的简单使用

1、什么是Axios

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

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

2、Axios传参

在这里插入图片描述

在这里插入图片描述

3、await使用

在这里插入图片描述

  • 如果调用某个方法的返回值是Promise 实例,则前面可以添加 await
  • await只能用在被 async 修饰的方法中

4、使用解构赋值

在这里插入图片描述

在这里插入图片描述上面这个res.data 是真实数据中的data属性的值

解构赋值的时候,使用:进行重命名

  • 1.调用axios 之后,使用async/ await进行简化
  • 2.使用解构赋值,从 axios封装的大对象中,把 data 属性解构出来
  • 3.把解构出来的 data属性,使用冒号进行重命名,一般都重命名为{ data: res }

5、基于Axios.get 和 Axios.post 发起请求

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


八、vue-cli

1、什么是单页面应用程序

单页面应用程序(英文名: Single Page Application)简称SPA,顾名思义,指的是一个 Web 网站中只有唯一的一个HTML页面,所有的功能与交互都在这唯一的一个页面内完成。

在这里插入图片描述

2、什么是vue-cli

vue-cli是Vue.js 开发的标准工具。它简化了程序员基于webpack 创建工程化的Vue项目的过程。

引用自vue-cli官网上的一句话:
程序员可以专注在撰写应用上,而不必花好几天去纠结webpack配置的问题。

3、vue-cli 安装和使用

vue-cli是 npm 上的一个全局包,使用npm install 命令,即可方便的把它安装到自己的电脑上:

npm install -g @vue/cli

基于vue-cli 快速生成工程化的Vue项目:

vue create 项目的名称

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
切记:vue的安装路径不能有中文,不仅仅是文件名,是整个路径都不能有中文

4、vue-src目录下文件构成

  • assets文件夹:存放项目中用到的静态资源文件,例如: css样式表、图片资源
  • components文件夹:程序员封装的、可复用的组件,都要放到components目录下
  • main.js是项目的入口文件。整个项目的运行,要先执行main.js
  • App.vue是项目的根组件。|

5、vue项目运行流程

在工程化的项目中,vue要做的事情很单纯:
通过 main.js 把 App.vue 渲染到 index.html 的指定区域中。
其中:

  • App.vue 用来编写待渲染的模板结构
  • index.html 中需要预留一个el区域
  • main.js 把 App.vue 渲染到了 index.html 所预留的区域中
// 导入 vue 这个包 得到 vue 构造函数 相当于 <script src="./lib/vue@2.7.13.js"></script>
import Vue from 'vue'
// 导入 APP.vue 根组件,后面会把 APP.vue中的模板结构,渲染到 HTML 页面中
import App from './App.vue'

Vue.config.productionTip = false

// 创建 Vue 的实例对象
new Vue({
  //把 render 函数指定的组件,渲染到 HTML 页面中
  render: h => h(App),
}).$mount('#app')

// 这里 Vue 实例的 $mount()方法,和el属性的作用完全一样 绑定 index.html 页面中要被渲染的区域 div#app
// 最后会把 div#app 这一层覆盖掉

在这里插入图片描述
暂且这样,后面再理解


九、vue组件

1、什么是组件化开发

组件化开发指的是:
根据封装的思想,把页面上可重用的UI结构封装为组件,从而方便项目的开发和维护

组件是对UI结构的复用

2、vue中的组件化开发

vue是一个支持组件化开发的前端框架。
vue 中规定︰组件的后缀名是.vue。之前接触到的App.vue 文件本质上就是一个vue的组件。

3、vue组件的三个组成部分

每个.vue 组件都由3部分构成,分别是:

  • template ->组件的模板结构
  • script ->组件的JavaScript行为
  • style ->组件的样式
<template>
	<div class="hello">
		<h1>{{username}}</h1>
	</div>
</template>

<script>
// 默认导出 固定写法
export default {
	// data 数据源
	// 注意:vue组件中 data 不和 html 中一样,不能指向对象
	// 组件中的 data 必须是一个函数
	data() {
		// 这个 return 出去的 {} 中,可以定义数据
		return {
			username: 'hdat'
		}
	}
}
</script>

<style>
</style>

4、vue组件的methods方法

<template>
	<div class="hello">
		<h1>{{username}}</h1>
	</div>
</template>

<script>
// 默认导出 固定写法
export default {
	// data 数据源
	// 注意:vue组件中 data 不和 html 中一样,不能指向对象
	// 组件中的 data 必须是一个函数
	data() {
		// 这个 return 出去的 {} 中,可以定义数据
		return {
			username: 'hdat'
		}
	},
	methods: {
		change() {
			// 在组件中,this 就表示当前组件的实例对象  不再是Vue的实例对象了
		}
	},
	// 当前组件的侦听器
	watch: {
		
	},
	// 当前组件的计算属性
	computed: {
		
	},
	// 当前组件的过滤器 v3没有
	filters: {
		
	}
}
</script>

<style>
	.hello {
		background-color: antiquewhite;
	}
</style>

在组件中,this 就表示当前组件的实例对象 不再是Vue的实例对象了
只有data有变化,其他的还和之前一样

5、vue组件的根节点及less的使用

使用 less ,需要在 style 属性后面添加 lang 属性

<style lang="less">
	.hello {
		background-color: antiquewhite;
	}
</style>

组件中只有唯一一个根节点 一个div , 如果想用两个,就在上面再来个 div 包住

6、vue组件之间的父子关系

在这里插入图片描述

7、使用vue组件的三个步骤

在这里插入图片描述

导入注册使用

8、注册全局组件

通过components注册的是私有子组件

例如:

在组件A的 components节点下,注册了组件F。则组件F只能用在组件A中;不能被用在组件C中。

在vue项目的 main.js 入口文件 中,通过Vue.component()方法,可以注册全局组件。示例代码如下:

// 导入需要全局注册的组件
import Count from '@/components/Count.vue'

//参数1:字符串格式,表示组件的“注册名称”
//参数2:需要被全局注册的那个组件
Vue.component('MyCount',Count)

十、vue组件的props (道具)

1、什么是 props 属性

props是组件的自定义属性,在封装通用组件的时候,合理地使用props可以极大的提高组件的复用性!

在这里插入图片描述

在这里插入图片描述

可以结合 v-bind 使用自定义属性 ,传过去的就是一个数值

在这里插入图片描述

2、props 自定义属性只读

在这里插入图片描述

在这里插入图片描述

3、props 的 default 默认值

在这里插入图片描述

在这里插入图片描述

4、props 的 type 值类型

在这里插入图片描述

在这里插入图片描述

5、props 的 required 必填项

在这里插入图片描述

十一、vue组件之间样式冲突问题

1、scope

在这里插入图片描述
解决:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2、/deep/ 样式穿透

在父组件中修改子组件的样式

在这里插入图片描述

主要应用场景就是修改第三方组件样式的时候

103重新看
关于vue的原理

十二、vue生命周期

1、组件的生命周期

在这里插入图片描述

2、组件生命周期函数的分类

在这里插入图片描述

  • created 生命周期函数,非常常用。
  • 经常在它里面,调用 methods 中的方法,请求服务器的数据。
  • 并且,把请求到的数据,转存到 data 中,供 template 模板渲染的时候使用
  • 如果要操作当前组件的 DOM,最早只能在 mounted 阶段执行
  • 当数据变化之后,为了能够操作到最新的 DOM 结构,必须把代码写到 updated 生命周期函数中

十三、组件之间的数据共享

1、组件之间的关系

在这里插入图片描述

2、父组件向子组件传值

在这里插入图片描述

  • 子组件中的 props 的值只读,不建议修改,修改了之后不会影响父组件中绑定的值
  • 一般就是把 props 中的值存到data中,再进行操作

3、子组件向父组件传值

在这里插入图片描述

  • emit 发行 发表

4、兄弟组件之间的传值

在这里插入图片描述

在这里插入图片描述

也可以理解为 发布 和 订阅 

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

十四、ref引用

1、什么是ref引用

在这里插入图片描述

2、使用ref引用DOM元素

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

3、使用ref引用组件

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

有了子组件的实例对象,就相当于子组件的this,就可以直接调用子组件中的方法了

ref 引用

4、使用this.$nextTick(callback)

在 数据变化并重新渲染DOM后再操作DOM 的情况下使用

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

点击按钮切换成文本框并自动聚焦,更改inputVisible的值,隐藏按钮,显示文本框,这个时候,不能直接去操作文本框,因为现在只是数据发生改变,DOM还没有重新渲染,所以,还没有Input这个标签,所以调用会报错,这个时候使用nextTick 等DOM重新渲染完成后有Input了再进行操作。

问题:为什么不能写在updated中?

首先updated是和methods是平级的,这一点要注意。写在updated中每次数据发生变化,都会触发一次updated函数,这样的话,当输入框显示的时候没有问题,当输入框隐藏藏了,就找不到input了(这里用的是v-if),所以注意区分是不是特有的,如果是特有的,就用nextTick,如果是公共的,那就用updated

十五、数组中一些方法的补充

1、数组中的some循环方法

使用foreach循环的话,会导致循环停不下来,所以当遍历数组元素,找到所需要的数组元素后便不希望继续往下循环的情况下,可以使用some循环

在这里插入图片描述

2、数组中的every方法

在这里插入图片描述

3、数组中的reduce方法

十六、动态组件

1、什么是动态组件

动态组件指的是动态切换组件的显示与隐藏

2、如何实现动态组件的渲染

vue 提供一个内置的 component 组件,专门用来实现动态组件的渲染。

 <div class="box">
   <!-- 渲染 Left 组件和 Right 组件 -->
   <!-- 1. component 标签是 vue 内置的,作用:组件的占位符 -->
   <!-- 2. is 属性的值,表示要渲染的组件的名字 -->
   <!-- 3. is 属性的值,应该是组件在 components 节点下的注册名称 -->
	 <component :is="comName"></component>
 </div>

<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'

export default {
  data() {
    return {
      // comName 表示要展示的组件的名字
      comName: 'Left'
    }
  },
  components: {
    // 如果在“声明组件”的时候,没有为组件指定 name 名称,则组件的名称默认就是“注册时候的名称”
    Left,
    Right
  }
}
</script>

3、keep-alive 的使用

动态组件每次切换的时候,之前的组件就会被销毁。
使用 keep-alive 可以保持状态,组件被隐藏而不会被销毁,会被缓存。下次被激活还是原来的状态。

 <button @click="comName = 'Left'">展示 Left</button>
 <button @click="comName = 'Right'">展示 Right</button>

 <div class="box">
   <!-- 渲染 Left 组件和 Right 组件 -->
   <!-- 1. component 标签是 vue 内置的,作用:组件的占位符 -->
   <!-- 2. is 属性的值,表示要渲染的组件的名字 -->
   <!-- 3. is 属性的值,应该是组件在 components 节点下的注册名称 -->

   <!-- keep-alive 会把内部的组件进行缓存,而不是销毁组件 -->
   <!-- 在使用 keep-alive 的时候,可以通过 include 指定哪些组件需要被缓存; -->
   <!-- 或者,通过 exclude 属性指定哪些组件不需要被缓存;但是:不要同时使用 include 和 exclude 这两个属性 -->
   <keep-alive exclude="MyRight">
     <component :is="comName"></component>
   </keep-alive>
 </div>

4、keep-alive 对应的生命周期函数

当组件被缓存的时候,会自动触发组件的 deactivated 生命周期。
当组件被激活的时候,会自动触发组件的 activated 生命周期。

<script>
export default {
  name: 'MyLeft',
  data() {
    return {
      count: 0
    }
  },
  created() {
    console.log('Left 组件被创建了!')
  },
  destroyed() {
    console.log('Left 组件被销毁了~~~')
  },

  // 当组件第一次被创建的时候,既会执行 created 生命周期,也会执行 activated 生命周期
  // 当时,当组件被激活的时候,只会触发 activated 生命周期,不再触发 created。因为组件没有被重新创建
  activated() {
    console.log('组件被激活了,activated')
  },
  deactivated() {
    console.log('组件被缓存了,deactivated')
  }
}
</script>

5、keep-alive 的 include 属性

用来指定那些组件会被缓存

只有名称匹配的组件会被缓存,多个组件名之间使用英文的逗号进行分隔:

<!-- 只有MyRight 组件会被缓存 -->
<!-- 在使用 keep-alive 的时候,可以通过 include 指定哪些组件需要被缓存; -->
<!-- 或者,通过 exclude 属性指定哪些组件不需要被缓存;但是:不要同时使用 include 和 exclude 这两个属性 -->
<keep-alive include="MyRight">
  <component :is="comName"></component>
</keep-alive>

6、组件注册名称 和 组件声明时的 name 的区别

<script>
export default {
  // 当提供了 name 属性之后,组件的名称,就是 name 属性的值
  // 对比:
  // 1. 组件的 “注册名称” 的主要应用场景是:以标签的形式,把注册好的组件,渲染和使用到页面结构之中
  // 2. 组件声明时候的 “name” 名称的主要应用场景:结合 <keep-alive> 标签实现组件缓存功能;以及在调试工具中看到组件的 name 名称
  name: 'MyRight'
}
</script>

如果在“声明组件”的时候,没有为组件指定 name 名称,则组件的名称默认就是“注册时候的名称”

如果声明组件时为组件指定了 name 名称,那么组件的名称就是 name 属性的值, 注册组件的名称只是用来作为标签引入组件。

一般规范都会指定名称,如果不想区分,那就使这两个保持一致就好了。

十七、插槽

1、什么是插槽

插槽(slot)是 vue 为组件的组装者提供的能力,允许开发者在封装组件时,把不确定、希望由用户指定部分定义为插槽。

在这里插入图片描述

在这里插入图片描述

2、v-slot

vue 官方规定,每个 slot 插槽,都要有一个 name 名称。如果省略了,则有一个默认名称叫 default。

如果没有指定把自定义内容放到那个插槽中,他就会默认放到 default 插槽中

可以使用 v-slot 来指定内容放到那个插槽中,可以简写为 #

在这里插入图片描述

<!--App.vue-->
<div class="box" style="display: none;">
      <!-- 渲染 Left 组件和 Right 组件 -->
      <Left>
        <!-- 默认情况下,在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽之中 -->
        <!-- 1. 如果要把内容填充到指定名称的插槽中,需要使用 v-slot: 这个指令 -->
        <!-- 2. v-slot: 后面要跟上插槽的名字 -->
        <!-- 3. v-slot: 指令不能直接用在元素身上,必须用在 template 标签上 -->
        <!-- 4. template 这个标签,它是一个虚拟的标签,只起到包裹性质的作用,但是,不会被渲染为任何实质性的 html 元素 -->
        <!-- 5. v-slot: 指令的简写形式是 # -->
        <template #default>
          <p>这是在 Left 组件的内容区域,声明的 p 标签</p>
        </template>
      </Left>
    </div>
<!--Left.vue-->
<template>
  <div class="left-container">
    <h3>Left 组件</h3>
    <hr />
    <!-- 声明一个插槽区域 -->
    <!-- vue 官方规定:每一个 slot 插槽,都要有一个 name 名称 -->
    <!-- 如果省略了 slot 的 name 属性,则有一个默认名称叫做 default -->
    <slot name="default"></slot>
  </div>
</template>

3、v-slot 的后备内容

后备内容就是插槽的默认内容,当调用插槽的人并没有为其指定内容,那么可以展示默认内容

<slot name="default">
  <h6>这是 default 插槽的后备内容</h6>
</slot>

4、具名插槽的定义和使用

在这里插入图片描述

5、作用域插槽的用法

在这里插入图片描述

 <!--Article.vue -->
<!-- 文章的内容 -->
<div class="content-box">
  <!-- 在封装组件时,为预留的 <slot> 提供属性对应的值,这种用法,叫做 “作用域插槽” -->
  <slot name="content" msg="hello vue.js" :user="userinfo"></slot>
</div>
<script>
export default {
  // 首字母要大写
  name: 'Article',
  data() {
    return {
      // 用户的信息对象
      userinfo: {
        name: 'zs',
        age: 20
      }
    }
  }
}
</script>
<!--App.vue -->
<template #content="{ msg, user }">
  <div>
     <p>啊,大海,全是水。</p>
     <p>啊,蜈蚣,全是腿。</p>
     <p>啊,辣椒,净辣嘴。</p>
     <p>{{ msg }}</p>
     <p>{{ user.name }}</p>
   </div>
 </template>

十八、自定义指令

1、什么是自定义指令

vue官方提供了v-text、v-for、v-model、v-if等常用的指令。除此之外vue还允许开发者自定义指令

2、自定义指令的分类

私有自定义指令
全局自定义指令

3、私有自定义指令

bind函数只调用1次。当指令第一次绑定到元素时调用,当DOM更新时 bind函数不会被触发。update函数会在每次DOM更新时被调用

<div class="app-container">
    <h1 v-color="color">App 根组件</h1>
    <p v-color="'red'">测试</p>
    <button @click="color = 'green'">改变 color 的颜色值</button>
    <hr />
  </div>
</template>

<script>
import Left from '@/components/Left.vue'
import Article from '@/components/Article.vue'

export default {
  data() {
    return {
      color: 'blue'
    }
  },
  components: {
    Left,
    Article
  },
  // 私有自定义指令的节点
  directives: {
    // 定义名为 color 的指令,指向一个配置对象
    /* color: {
      // 当指令第一次被绑定到元素上的时候,会立即触发 bind 函数
      // 形参中的 el 表示当前指令所绑定到的那个 DOM 对象
      bind(el, binding) {
        console.log('触发了 v-color 的 bind 函数')
        el.style.color = binding.value
      },
      // 在 DOM 更新的时候,会触发 update 函数
      update(el, binding) {
        console.log('触发了 v-color 的 update 函数')
        el.style.color = binding.value
      }
    } */
    //简写
    color(el, binding) {
      el.style.color = binding.value
    }
  }
}
</script>

4、全局自定义指令

全局共享的自定义指令需要通过“Vue.directive()”进行声明,在main.js中

// 全局自定义指令
Vue.directive('color', {
  bind(el, binding) {
    el.style.color = binding.value
  },
  update(el, binding) {
    el.style.color = binding.value
  }
})
 
//简写
Vue.directive('color', function(el, binding) {
  el.style.color = binding.value
})

十九、ESLint

1、什么是ESLint

是一个代码检查工具,为了代码的规范化

2、安装ESLint

vue create demo3-eslint

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

3、vscode 配置ESLint

二十、axios挂载到vue原型上

1、Axios的基本使用

安装

npm i axios -S

单个组件使用

<template>
  <div class="left-container">
    <h3>Left 组件</h3>
    <button @click="getInfo">发起 GET 请求</button>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  methods: {
    async getInfo() {
      const { data: res } = await axios.get('http:www.liuolongbin.top:3006/api/get')
      console.log(res)
    }
  }
}
</script>

<style lang="less" scoped>
.left-container {
  background-color: orange;
  min-height: 200px;
  flex: 1;
}
</style>

2、Axios挂载到vue原型上使用

//main.js
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'

Vue.config.productionTip = false

// 全局配置 axios 的请求根路径
axios.defaults.baseURL = 'http://www.liulongbin.top:3006'
// 把 axios 挂载到 Vue.prototype 上,供每个 .vue 组件的实例直接使用  prototype原型
Vue.prototype.$axios = axios

// 今后,在每个 .vue 组件中要发起请求,直接调用 this.$axios.xxx
// 但是,把 axios 挂载到 Vue 原型上,有一个缺点:不利于 API 接口的复用!!!

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

<!--left.vue-->
<template>
  <div class="left-container">
    <h3>Left 组件</h3>
    <button @click="getInfo">发起 GET 请求</button>
    <button @click="btnGetBooks">获取图书列表的数据</button>
  </div>
</template>

<script>
// import axios from 'axios'

export default {
  methods: {
    async getInfo() {
      const { data: res } = await this.$axios.get('/api/get')
      console.log(res)
    },
    // 点击按钮,获取图书列表的数据
    async btnGetBooks() {
      const { data: res } = await this.$axios.get('/api/getbooks')
      console.log(res)
    }
  }
}
</script>

<style lang="less" scoped>
.left-container {
  background-color: orange;
  min-height: 200px;
  flex: 1;
}
</style>

3、Axios直接挂载到vue原型上使用的缺点

缺点:无法实现接口的复用

二一、前端路由

1、什么是前端路由

路由(router)就是对应关系
Hash地址(#) 与 组件之间的对应关系。

2.SPA与路由

在这里插入图片描述

3.前端路由的工作方式

在这里插入图片描述

4.实现简易的前端路由

可以使用动态组件实现

<template>
  <div class="app-container">
    <h1>App 根组件</h1>

    <a href="#/home">首页</a>
    <a href="#/movie">电影</a>
    <a href="#/about">关于</a>
    <hr />

    <component :is="comName"></component>
  </div>
</template>

<script>
// 导入组件
import Home from '@/components/Home.vue'
import Movie from '@/components/Movie.vue'
import About from '@/components/About.vue'

export default {
  name: 'App',
  data() {
    return {
      // 在动态组件的位置,要展示的组件的名字,值必须是字符串
      comName: 'Home'
    }
  },
  created() {
    // 只要当前的 App 组件一被创建,就立即监听 window 对象的 onhashchange 事件
    window.onhashchange = () => {
      console.log('监听到了 hash 地址的变化', location.hash)
      switch (location.hash) {
        case '#/home':
          this.comName = 'Home'
          break
        case '#/movie':
          this.comName = 'Movie'
          break
        case '#/about':
          this.comName = 'About'
          break
      }
    }
  },
  // 注册组件
  components: {
    Home,
    Movie,
    About
  }
}
</script>

<style lang="less" scoped>
.app-container {
  background-color: #efefef;
  overflow: hidden;
  margin: 10px;
  padding: 15px;
  > a {
    margin-right: 10px;
  }
}
</style>

二一、vue-router的基本使用

1、什么是vue-router

vue-router是vue.js官方给出的路由解决方案。它只能结合vue项目进行使用,能够轻松的管理SPA项目中组件的切换。
vue-router的官方文档地址:httpsa// router.vuejs.org/zh/

2、vue-router 安装和配置的步骤

在这里插入图片描述
1.安装

npm i vue-router@3.5.2 -S

2.创建
在这里插入图片描述

// src/router/index.js 就是当前项目的路由模块
import Vue from 'vue'
import VueRouter from 'vue-router'


// 把 VueRouter 安装为 Vue 项目的插件
// Vue.use() 函数的作用,就是来安装插件的
Vue.use(VueRouter)

// 创建路由的实例对象
const router = new VueRouter({
  // routes 是一个数组,作用:定义 “hash 地址” 与 “组件” 之间的对应关系
  routes: [
    // 重定向的路由规则
    { path: '/', redirect: '/home' },
    // 路由规则
    { path: '/home', component: Home },
    // 需求:在 Movie 组件中,希望根据 id 的值,展示对应电影的详情信息
    // 可以为路由规则开启 props 传参,从而方便的拿到动态参数的值
    { path: '/movie/:mid', component: Movie, props: true },
    {
      path: '/about',
      component: About,
      // redirect: '/about/tab1',
      children: [
        // 子路由规则
        // 默认子路由:如果 children 数组中,某个路由规则的 path 值为空字符串,则这条路由规则,叫做“默认子路由”
        { path: '', component: Tab1 },
        { path: 'tab2', component: Tab2 }
      ]
    },
    { path: '/login', component: Login },
    { path: '/main', component: Main }
  ]
})


//向外共享路由的实例对象
export default router


3.挂载
在这里插入图片描述

//main.js
import Vue from 'vue'
import App from './App2.vue'
// 导入路由模块,目的:拿到路由的实例对象
// 在进行模块化导入的时候,如果给定的是文件夹,则默认导入这个文件夹下,名字叫做 index.js 的文件
import router from '@/router'

// 导入 bootstrap 样式
import 'bootstrap/dist/css/bootstrap.min.css'
// 全局样式
import '@/assets/global.css'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  // 在 Vue 项目中,要想把路由用起来,必须把路由实例对象,通过下面的方式进行挂载
  // router: 路由的实例对象
  router
}).$mount('#app')


4.声明路由连接和占位符

//index.js
// 创建路由的实例对象
const router = new VueRouter({
  // routes 是一个数组,作用:定义 “hash 地址” 与 “组件” 之间的对应关系
  routes: [
    // 重定向的路由规则
    { path: '/', redirect: '/home' },
    // 路由规则
    { path: '/home', component: Home },
    // 需求:在 Movie 组件中,希望根据 id 的值,展示对应电影的详情信息
    // 可以为路由规则开启 props 传参,从而方便的拿到动态参数的值
    { path: '/movie/:mid', component: Movie, props: true },
    {
      path: '/about',
      component: About,
      // redirect: '/about/tab1',
      children: [
        // 子路由规则
        // 默认子路由:如果 children 数组中,某个路由规则的 path 值为空字符串,则这条路由规则,叫做“默认子路由”
        { path: '', component: Tab1 },
        { path: 'tab2', component: Tab2 }
      ]
    },
    { path: '/login', component: Login },
    { path: '/main', component: Main }
  ]
})
    <!-- 只要在项目中安装和配置了 vue-router,就可以使用 router-view 这个组件了 -->
    <!-- 它的作用很单纯:占位符 -->
    <router-view></router-view>

3、使用 router-link 替代 a 链接

    <!-- 当安装和配置了 vue-router 后,就可以使用 router-link 来替代普通的 a 链接了 -->
    <!-- <a href="#/home">首页</a> -->
    <router-link to="/home">首页</router-link>
    <!-- 注意1:在 hash 地址中, / 后面的参数项,叫做“路径参数” -->
    <!-- 在路由“参数对象”中,需要使用 this.$route.params 来访问路径参数 -->

    <!-- 注意2:在 hash 地址中,? 后面的参数项,叫做“查询参数” -->
    <!-- 在路由“参数对象”中,需要使用 this.$route.query 来访问查询参数 -->

    <!-- 注意3:在 this.$route 中,path 只是路径部分;fullPath 是完整的地址 -->
    <!-- 例如: -->
    <!-- /movie/2?name=zs&age=20 是 fullPath 的值 -->
    <!-- /movie/2 是 path 的值 -->
    <router-link to="/movie/1">洛基</router-link>
    <router-link to="/movie/2?name=zs&age=20">雷神</router-link>
    <router-link to="/movie/3">复联</router-link>
    <router-link to="/about">关于</router-link>

    <hr />

4、路由重定向

路由重定向指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面。通过路由规则的redirect属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

在这里插入图片描述

5、嵌套路由

在这里插入图片描述

<!--about.vue-->
<template>
  <div class="about-container">
    <h3>About 组件</h3>

    <!-- 子级路由链接 -->
    <router-link to="/about">tab1</router-link>
    <router-link to="/about/tab2">tab2</router-link>

    <hr />

    <!-- 子级路由占位符 -->
    <router-view></router-view>
  </div>
</template>
//index.js
{
      path: '/about',
      component: About,
      //路由重定向  从/about 重定向到 /about/tab1 也就是默认展示tab1  
      // redirect: '/about/tab1',
      children: [
        // 子路由规则
        // 默认子路由:如果 children 数组中,某个路由规则的 path 值为空字符串,则这条路由规则,叫做“默认子路由”
        { path: '', component: Tab1 },
        { path: 'tab2', component: Tab2 }
      ]
    },

通过 children 属性声明子路由规则
用重定向或者默认子路由都可以设置默认路由

6、动态路由匹配

动态路由指的是:把 Hash地址中可变的部分定义为参数项,从而提高路由规则的复用性。

在这里插入图片描述获取参数值

 //index.js
 // 需求:在 Movie 组件中,希望根据 id 的值,展示对应电影的详情信息
 // 可以为路由规则开启 props 传参,从而方便的拿到动态参数的值
 { path: '/movie/:mid', component: Movie, props: true },
 <!-- movie.vue -->
<template>
  <div class="movie-container">
    <!-- this.$route 是路由的“参数对象” -->
    <!-- this.$router 是路由的“导航对象” -->
    <h3>Movie 组件 --- {{ $route.params.mid }} --- {{ mid }}</h3>
    <button @click="showThis">打印 this</button>
  </div>
</template>

<script>
export default {
  name: 'Movie',
  // 接收 props 数据
  props: ['mid'],
  methods: {
    showThis() {
      console.log(this)
    }
  }
}
</script>
 <!-- app.vue -->
 <!-- 注意1:在 hash 地址中, / 后面的参数项,叫做“路径参数” -->
 <!-- 在路由“参数对象”中,需要使用 this.$route.params 来访问路径参数 -->

 <!-- 注意2:在 hash 地址中,? 后面的参数项,叫做“查询参数” -->
 <!-- 在路由“参数对象”中,需要使用 this.$route.query 来访问查询参数 -->

 <!-- 注意3:在 this.$route 中,path 只是路径部分;fullPath 是完整的地址 -->
 <!-- 例如: -->
 <!-- /movie/2?name=zs&age=20 是 fullPath 的值 -->
 <!-- /movie/2 是 path 的值 -->
 <router-link to="/movie/1">洛基</router-link>
 <router-link to="/movie/2?name=zs&age=20">雷神</router-link>
 <router-link to="/movie/3">复联</router-link>

7、声明式导航&编程式导航

在这里插入图片描述
vue-router 中的编程式导航API

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

<template>
  <div class="movie-container">
    <button @click="goback">后退</button>
    <!-- 在行内使用编程式导航跳转的时候,this 必须要省略,否则会报错! -->
    <button @click="$router.back()">back 后退</button>
    <button @click="$router.forward()">forward 前进</button>
  </div>
</template>

<script>
export default {
  name: 'Movie',
  methods: {
    goback() {
      // go(-1) 表示后退一层
      // 如果后退的层数超过上限,则原地不动
      this.$router.go(-1)
    }
  }
}
</script>

8、导航守卫

在这里插入图片描述

1、全局前置守卫

//index.js
// 为 router 实例对象,声明全局前置导航守卫
// 只要发生了路由的跳转,必然会触发 beforeEach 指定的 function 回调函数
router.beforeEach(function(to, from, next) {
  // to 表示将要访问的路由的信息对象
  // from 表示将要离开的路由的信息对象
  // next() 函数表示放行的意思
  // 分析:
  // 1. 要拿到用户将要访问的 hash 地址
  // 2. 判断 hash 地址是否等于 /main。
  // 2.1 如果等于 /main,证明需要登录之后,才能访问成功
  // 2.2 如果不等于 /main,则不需要登录,直接放行  next()
  // 3. 如果访问的地址是 /main。则需要读取 localStorage 中的 token 值
  // 3.1 如果有 token,则放行
  // 3.2 如果没有 token,则强制跳转到 /login 登录页
  if (to.path === '/main') {
    // 要访问后台主页,需要判断是否有 token
    const token = localStorage.getItem('token')
    if (token) {
      next()
    } else {
      // 没有登录,强制跳转到登录页
      next('/login')
    }
  } else {
    next()
  }
})

在这里插入图片描述案例
p193

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霍志杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值