2022秋招-前端学习记录12-Vue专题2

Vue常用的指令

① v-html、② v-bind、③ v-on、④ v-if、⑤ v-show、⑥ v-for、⑦ v-model

① v-html
将v-html的内容(一般是个标签体)解析后展示在网页
效果等同于:<h1><a href="http://www.baidu.com">百度一下</a></h1>
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

引:img的src 与 a标签的href 区别?

b站技术蛋老师:https://www.bilibili.com/video/BV1jJ411P7iD

src: Source    资源
常用src的标签: img、style、script、input 和 iframe
src是下载资源后嵌入dom,直接构成文档内容。在请求src资源时会将其指向的资源 下载并应⽤到⽂档内,如js脚本,img图⽚和frame等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕。

href: Hypertext Reference    超文本引用/参照
常用href的标签: a、link
href是元素或文档与指定资源联通,是引用。⽤来建立和当前元素或⽂档之间的连接通道,当浏览器识别到它指向的⽂件时,就会并行下载资源,不会停止对当前文档的处理。

 
 
② v-bind
用来绑定data里面的变量,简写用冒号 : ;不用bind的话,那里面写的就会当做字符串来处理,而不会去找这个变量数据。
v-bind的动态绑定提一句,可以用 :class绑定css的样式,用 :style直接绑定内联样式变量。
效果等同于:
<img src="https://cn.vuejs.org/images/logo.png" alt="">
<a href="http://www.baidu.com"></a>
在这里插入图片描述在这里插入图片描述

③ v-on
实现事件监听功能,简写用 @ ;
在这里插入图片描述
在这里插入图片描述
点击加号按钮,数字增大,点击减号按钮,数字减小。
在这里插入图片描述

④ v-if
v-if的值只有true的时候,标签才显示在文档流,如果值为false,那么该标签直接被删掉,直接不渲染。
伴随着v-else:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
⑤ v-show
和 v-if 的效果差不多,没有v-else
v-if和v-show的区别,参考 记录7-Vue专题

⑥ v-for
遍历,可以增加列表
在这里插入图片描述
在这里插入图片描述
效果:
在这里插入图片描述
⑦ v-model
表单里的双向绑定:
在这里插入图片描述
在这里插入图片描述
删数据的话,后面显示的数据也会跟着一起消失。
在这里插入图片描述

引:哪些数组的方法是响应式的?(直接用索引值去改数组的数据页面会没反应,所以要借助数组的响应式方法来改。)

响应式是指,界面显示和数据的变化一起变化

会响应式:push pop shift unshift splice reverse反转 sort 排序,注意这些都是会改变数组自身的方法 Array.prototype.xxxx()

注意!!! 直接通过索引值修改数组中的元素 不能响应式,,所以不建议使用
this.names[2]=“ddddd”; // 在界面上是不会显示变化的,,但是这样元素确实是改掉了

methods: {
	btnClick(){
	  // 响应式是指,界面显示和数据的变化一起变化  
	
	  // 1.push方法 可以响应式
	  // this.names.push('asd', 'ss', 'gh');
	
	  // 2.pop方法 删最后一位元素 可以响应式
	  // this.names.pop();
	
	  // 3.shift方法 删第0位元素  可以响应式
	  // this.names.shift();
	
	  // 4.unshift方法 在第0位之前添加元素 可以响应式
	  // this.names.unshift('aaa', 'kl');
	
	  // 5.splice 3个参数:start/删除个数/要替换的元素;可以响应式
	  // this.names.splice(2, 2, 'ffff');
	
	  // 6.sort 排序 可以响应式
	  // this.names.sort();
	  // 7.reverse 反转 可以响应式
	  // this.names.reverse();
	
	  // 注意!!! 直接通过索引值修改数组中的元素  不能响应式,,所以不建议使用
	  //this.names[2]="ddddd"; // 在界面上是不会显示变化的,,但是这样元素确实是改掉了
	
	  // 那么建议用这种方式修改数组中的元素
	  // this.names.splice(2, 1, 'ddddd');
	  // 或者
	  Vue.set(this.names, 2, 'ddddd')      
	}
}

 

Vue的生命周期

Vue的生命周期,实际上可以说是 Vue实例的生命周期
Vue实例的生命周期:Vue 实例有⼀个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 ->销毁 等⼀系列过程,我们称这是Vue的⽣命周期。

我们在非脚手架的普通程序里 写代码的时候,通常都是需要写一个

const app = new Vue({
	el: '#app', 
	data:{msg: 'hello'}
})

那么,在new的过程中发生了什么?new完之后又能发生什么?
这就是从生命周期开始说了,
生命周期钩子 = 生命周期事件 = 生命周期函数
b站参考视频:https://www.bilibili.com/video/BV1sb411M7RT
请添加图片描述
1、new Vue({ el: ‘#app’, data:{msg: ‘hello’} }) -> 先初始化一个空的Vue实例对象,里面暂时没什么东西,只有一些默认事件和生命周期函数 -> 到达第一个钩子节点 beforeCreated(){} , 此时data和methods里的都还是undefined,$el也没挂载。
2、对data和methods进行初始化init -> 到达第二个钩子节点 created(){} ,此时data和methods里有初始化的东西了,要操作data或调用methods中方法的话,最早可以从created(){}开始。
3、对 $el挂载的dom和template里的dom进行编译,形成模板,即虚拟dom,但是先不渲染成真实dom -> 到达第三个钩子节点 beforeMount(){} (渲染真实dom前)
4、把虚拟dom渲染成真实的dom -> 到达第四个钩子节点 mounted(){} (真实dom有了)用户可以看到渲染好的页面了,如果数据需要做个改变,最早从这里开始改,才可以实时看到页面数据的更新信息。->执行完mounted,Vue实例创建阶段完全结束,即从数据变化到页面渲染已经结束了,没有其他操作了的话,这个实例就这样展现了。
5、初始化结束,进入运行阶段了,data的数据被改变了就会自动触发下面的钩子函数 ->到达第五个钩子节点 beforedUpdate(){} (data数据改变了),此时数据是新改变了的,但是页面显示的还没跟着改。
6、页面根据新改变的数据,重新渲染出一份新的虚拟dom树,再挂载映射成真实dom页面,这时候完成了data(model层)到 视图(view层)的更新 -> 到达第六个钩子节点 updated(){} (data连带着页面一起变了) ,页面和data数据保持同步了,都是最新的。只要数据再改变,就可以触发循环回到第五步。
7、页面一关,触发when vm.$destroy() is called这个函数 -> 到达第七个钩子节点 beforeDestroy(){} (销毁前) ,从运行阶段,进入到销毁阶段了,但是这里的data、methods、指令等等都还可以调用,还没有真正执行销毁过程。
8、这一步的data、指令什么的,都不能用了 -> 到达第八个钩子节点 destroyed(){} (已经销毁)

八个钩子函数

生命周期钩子函数描述
beforeCreate(){}(创建前)vue实例的挂载元素$el和数据对象 data都是undefined, 还未初始化
created(){} (创建后)此时data和methods已经被初始化了,要操作data或调用methods中方法的话,最早从created(){}开始
beforeMount(){} (渲染真实dom前)虚拟dom已经生成了,还没渲染成真实dom树
mounted(){} (真实dom有了)用户可以看到渲染好的页面了,如果数据改变了,最早从这里改,才可以实时看到页面数据的更新信息
beforedUpdate(){} (data数据改变了)此时数据是新改变了的,但是页面显示的还没跟着改
updated(){} (data连带着页面一起变了)此时页面已经根据data变化完成,页面和data数据保持同步了,都是最新的
beforeDestroy(){} (销毁前)从运行阶段,进入到销毁阶段了,但是这里的data、methods、指令等等都还可以调用,还没有真正执行销毁过程
destroyed(){} (已经销毁)已经被完全销毁,所有数据,方法、指令等等,都不可用了

 

Vue组件的通信方式

1、父传子props;2、子传父this.$emit();3、兄弟互传EventBus;4、Vuex公共数据管理工具

组件通信分为三种:父组件传数据给子组件、子组件传数据给父组件、兄弟组件之间互相传数据。

方式有好多种,只讲常见的几种:
1、父传子:v-bind(父端 冒号绑定) + props(子端 接收) 关键是props接收

父组件本身 -> 正常写就行;
父组件绑定的dom模板 -> 那里引用components挂的子组件时,用 v-bind的原因是 告诉vue 这是一个 JavaScript 表达式而不是一个字符串,从而将变量传进去。
子组件本身 -> 要 用props属性来定义要接收的数据,比如数据类型,数据初始值什么的。如果子组件的本地data属性要拿到props属性里面的数据,可以另外定义一个变量来接收,值就直接this.该变量。
子组件绑定的dom模板 -> 使用正常的取数据就可以用。
在这里插入图片描述

2、子传父: this.$emit(子端 发送) + v-on(父端 @ 接收 ) 关键是 this.$emit 发送

在子组件的方法里,想办法执行这条语句 this.$emit('变量名', 参数)
在父组件绑定的dom模板里,它的子组件标签内部,使用v-on指令,简写@+emit传来的变量名=父组件用来接收参数的方法名
父组件的方法里,负责接收的方法要与父组件的方法名一样,参数就是子组件传过来的数据了。要在本地data使用这些数据,现在data里初始化几个变量,那么再方法里直接this.data的变量名=参数

在这里插入图片描述

3、兄弟组件互相通信:EventBus
b站参考视频:https://www.bilibili.com/video/BV1Gq4y1p7UM
这个方法有比较多的坑,就不细讲了,下面说一下基本逻辑和要背的要点:
Vue 的 EventBus叫做事件总线,基本方法是:

单独抽出一个 bus.js 文件,里面写如下代码就创建好了一个事件总线,没错,就是这么简单

import Vue from 'vue'
export const EventBus = new Vue()

需要通信的组件都要引入这个bus.js,然后就可以使用 bus.js导出的空Vue对象里面带的emit方法和on方法进行发布消息和 接收(订阅)消息了。

// 在A组件
import { EventBus } from "../bus.js";
export default {
  methods: {
    sendMsg() {      
      EventBus.$emit("aMsg", '这段是要发布出去的字符串数据'); // $emit 是发布消息 
    }
  }
}; 
// 在B组件,一般这个方法写在Created里头,生命周期函数自动执行,自动获取。
EventBus.$on("aMsg", (msg) => { // $on 是接收(订阅)消息
      //发送来的消息
      this.msg = msg; // msg='这段是要发布出去的字符串数据' 
    });

坑点:
就是说,这个 $on事件是不会自动清楚销毁的,需要我们手动来销毁。否则会出现重复触发事件的问题。
解决方法:
// 尤大大的建议:在B组件的 beforeDestory 钩子里面,使用$off方法将on手动销毁掉。
beforeDestroy () {
bus.$off(‘aMsg’, this.myhandle)
}

4、公共的数据管理工具:Vuex

引:Vuex的定义和用法

vuex算是个插件,如果不去配套,那就需要额外用 npm install来引入,或者像引入Vue.js文件一样或者cdn引入Vuex.js。

b站视频:https://www.bilibili.com/video/BV1gt4y1X78g

Vuex就是个公共数据仓库,只要在某祖先组件里面加入一次,那么该祖先下面的所有后代都可以直接使用Vuex了,不需要额外再引入。
(所以在脚手架里,一般是在最最开头的main.js里面加上,那么从app组件以及app的后代组件开始,都可以直接拿来用。下图是脚手架里的Vuex引用,从store文件夹里面导出的一个store)
在这里插入图片描述
ok,引入Vuex之后,任何可以使用这东西的组件,不管是哪个组件,都可以从这个公共数据仓库里面取得数据,以及调用公共数据仓库里面的方法修改那些公共数据。
这样就算是实现了组件之间的通信(把需要传来传去的数据干脆抽出来放在一个公共部分,谁想取就取,哪个组件要改一次数据,那取了数据的所有组件里的那个公共数据就会跟着一起都被改掉了)

Vuex的具体用法:
Vuex是个仓库,被main.js引入,其对象名为store;
store对象有一共有5个属性
state: 用来保存公共数据;
mutations: 因为最好不要在组件里面改state的数据,要在mutations对象下面的方法属性里面,造一些方法来动态改动属性;而组件想要拿到改动之后的数据,直接找到mutations里面的方法调用即可;
getters: 计算方法放里头,方法几乎都要把数据return出去,可以把数据缓存起来,多次重复调用只用执行一次,不用执行多次,和vue实例里的computed属性差不多,只有数据发生变化才会重新计算;
actions: 类似于 mutations,但是 是用来替代mutations进行异步操作的;
modules: 子仓库统一管理的地方,如果state的数据太多太杂,可以适当分成一类一类的仓库进行存放。

只要在某祖先组件里面加入一次store,那么该祖先下面的所有后代都可以直接使用该公共数据仓库了,不需要额外再引入。

Vuex的用法:
1、取state里属性为 a 的值:
在组件里这样可以写:<h2>{{this.$store.state.a}}<h2>this.message = this.$store.state.a等等

2、调用mutations属性里存着的dda(state){…}方法动态改变state的值,注意点,这里的state要写,不用额外定义,系统会自动给mutations的方法传递一个state参数
在这里插入图片描述
在组件里这样可以写 this.$store.commit('dda'); // 这句是放在组件里,一般在函数里,调用函数就可以执行
在这里插入代码片

3、getters的计算方法怎么用:
比如图片的方法,就是getters对象里的属性之一
在这里插入图片描述
用法this.$store.getters.powerCounter,这里就会得到return后的数据。
如下:
在这里插入图片描述

引:mixin混入对象,以及和vuex的区别

写的很好 : https://www.jianshu.com/p/bcff647d24ec
比如我的hello组件和world组件 有比较多的共同的数据和方法,但是不像vuex那样共享,变量是自己的,内容一样而已,各改各的。
那么可以将这部分抽离出来,单独定义出一个对象来,这个对象定义如下:(里面的格式和Vue实例里面的东西一样一样的)

// 在mymixin01.js里面定义如下
export const mixin01 = {
  data() {
    return {
      message: 'hello',
      foo: 'abc'
    }
  },
  created() {
	this.hello();
  }
  methods: {
	hello(){
		console.log('hello!!')
	}
  }
}

在需要的组件里混入:

// 当前组件
<template>
<div></div>
</template>
<script>
import {mixin01} from './assets/mymixin01.js' // 把文件引入进来
export default {
  // 这一步就是混入对象的关键,使用mixins属性来添加
	mixins: [mixin01], 
	data(){
		return{message: 'hello!!!',} 
	}
	created() {
		this.hello();
  	}
  	methods: {
		hello(){
			console.log('My Hello')
		}
	}
}
</script>

混入对象mixin01的特点:
这个对象抽离之后,当前组件要使用的话,用 mixins这个属性就可以添加,具体用法如上面的代码片,属性值要用数组表达,当需要混入别的公共组件就在后面添加即可。
①mixin01会和当前组件里的各个属性选项合并。
在这里插入图片描述

如果mixin01(官网叫:混入对象)的data里的属性和当前的data里的属性重复了,以当前的属性值数据为准;
methods、components、directives合并的过程中,mixin01的属性和当前组件的属性重复了,以当前的方法为准;
如果mixin01和当前组件也有生命周期钩子函数created执行,那么mixin01里面的先执行生命周期,当前组件的生命周期钩子函数后执行。

② mixin01的方法和参数在各组件中不共享
这种混入带来一个特点:如果两个组件都引入了 这个mymixin01.js作为混入对象,那么混入对象里的数据,一个组件里修改了这个公共部分的数据后,另一个组件里这部分的数据是不会改变的。
可以当做,混入的实质就是添加到本组件的属性内部了,转换成和本组件自定义的其他数据和方法一样,不独立了,别的组件没法无访问。

与vuex的区别

Vuex:用来做状态管理的,里面定义的变量在每个组件中均可以使用和修改,在任一组件中修改此变量的值之后,其他组件中此变量的值也会随之修改。

mixins:可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值的修改在组件中不会相互影响。

与公共组件的区别

公共组件:在父组件中引入组件,相当于在父组件中给出一片独立的空间供子组件(公共组件)使用,然后根据props来传值,但本质上两者是相对独立的。

mixins:则是在引入混入对象之后,与组件中的对象和方法进行合并,相当于扩展了组件的对象与方法,可以理解为二者重组形成了一个新的组件

 

Vue路由route

什么是路由?

路由就是在做一个匹配的工作。路由是根据不同的 url 地址展示不同的内容或页面。

引:前端路由和后端路由,前端渲染和后端渲染:

写的很好:https://zhuanlan.zhihu.com/p/166175382

前端路由:
改变URL,但是页面不进行整体的刷新。

前端路由就是把不同路由对应不同页面的任务交给前端来做,每跳转到不同的URL都是使用前端的锚点路由。随着(SPA)单页应用的不断普及,前后端开发分离,目前项目基本都使用前端路由,在项目使用期间页面不会重新加载。

优点:
1.用户体验好,和后台网速没有关系。 需要每次都从服务器全部获取html。切换时可以快速展现给用户
2.实现了前后端的分离,方便开发。有很多框架都带有路由功能模块。

后端路由:
浏览器在地址栏中切换不同的 url 时,每次都向后台服务器发出请求(后端渲染),服务器响应请求,服务器渲染好整个页面, 并且将页面返回给客户端。

优点:
1.这种情况下渲染好的页面, 不需要单独加载任何的js和css, 可以直接交给浏览器展示, 这样也有利于SEO的优化
2.分担了前端的压力,html和数据的拼接都是由服务器完成。
缺点:
当项目十分庞大时,加大了服务器端的压力,HTML代码和数据以及对应的逻辑会混在一起, 不利于编写和维护。

后端渲染:

服务器直接生产渲染好 url 对应的HTML页面, 返回给客户端进行展示。 比如:jsp页面
好处:前端耗时少,即减少了首屏时间,模板统一在后端。前端(相对)省事,不占用客户端运算资源(解析模板)
坏处:占用服务器资源。

前端渲染:
你的浏览器从服务端拿到的html,这里面空荡荡的只有一个<div id="app"></div>这个入口的div以及下面配套的一系列js文件。你看到的页面其实是在浏览器中执行js代码后最终渲染出来的网页。这也是我们常说的前端渲染。
好处:前端渲染把渲染的任务交给了浏览器,通过客户端的算力来解决页面的构建,这个很大程度上缓解了服务端的压力。配合前端路由,无缝的页面切换体验自然是对用户友好的。
坏处:对SEO不友好

需要明确的是,只要在浏览器地址栏输入URL再回车,是一定会去后端服务器请求一次的(带来了history 404的问题)。而如果是在页面里通过点击按钮等操作,利用router库的api来进行的URL更新是不会去后端服务器请求的。

前端渲染与后端渲染对比:
后端渲染:
页面呈现速度:快,受限于用户的带宽
流量消耗:少一点点(可以省去前端框架部分的代码)
可维护性:差(前后端东西放一起,掐架多年,早就在闹分手啦)
seo友好度:好
编码效率:低(这个跟不同的团队不同,可能不对)
为什么要SSR???为了体验,还有SEO。

前端渲染:
页面呈现速度:主要受限于带宽和客户端机器的好坏,优化的好,可以逐步动态展开内容,感觉上会更快一点。
流量消耗:多一点点(一个前端框架大概50KB)当然,有的用后端渲染的项目前端部分也有在用框架。
可维护性:好,前后端分离,各施其职,代码一目明了。
SEO友好度:差,大量使用ajax,多数浏览器不能抓取ajax数据。
编码效率:高,前后端各自只做自己擅长的东西,后端最后只输出接口,不用管页面呈现,只要前后端人员能力不错,效率不会低。

 

引:路由的hash模式和history模式

hash用起来,我再也不敢嫌弃#这个符号丑了!

前端路由主要是有两种显示方式:
带有hash的前端路由,优点是兼容性高。缺点是url带有#号不好看
不带hash的history前端路由,优点是url不带#号,好看。缺点是既需要浏览器支持也需要后端服务器支持。

Hash模式:
带#号的路由,浏览器不会对 #号 后面的路径对服务端发起路由请求。如下这两个地址:http://www.baidu.com/#/user/1和http://www.baidu,com/#/home/about 其实到服务端都是去请求http://www.baidu.com 这个页面的内容。
前端的router库通过捕捉 #号 后面的数据,来告诉前端库(比如Vue)要渲染对应的页面。这个模式后端只需要给前端返回http://localhost对应的html,就不用返回别的了,剩下具体是#号后面的哪个页面,就由前端路由去判断便可。

History模式:
不带 #号 的路由,也就是我们通常能见到的URL形式。 这个api在IE10才开始支持,兼容性不太好。

部署 Vue 应用后,直接访问子路由或在子路由下刷新出现 404 空白的原因分析及对应的解决方法: https://www.bilibili.com/video/BV1yw411d7wS

一旦在浏览器地址栏输入http://localhost/user/1再回车,这个URL是会向后端发起请求的。(只要在浏览器地址栏输入URL再回车,是一定会去后端服务器请求一次的),后端路由表里如果没有配置相应的路由,那么自然就会返回一个404了!这也就是很多朋友在生产模式遇到404页面的原因。

那么很多人会问了,那为什么我在开发模式下没问题呢?那是因为vue-cli在开发模式下帮你启动的那个express开发服务器帮你做了这方面的配置。理论上在开发模式下本来也是需要配置服务端的,只不过vue-cli都帮你配置好了,所以你就不用手动配置了。

解决生产模式下,history模式404问题:在后端服务器那里,配置一个index.html,当前端输入url回车在服务器那边匹配不到文件的时候,就把这个index.html返回给客户端,index.html里配置一些东西,具体不清楚,没学,但是客户端拿到这个html之后,router库就可以开始工作了,开始获取地址栏的URL信息,然后再告诉前端库(比如Vue)渲染对应的页面。到这一步就跟hash模式是类似的了。

引:vue-router 有哪几种导航守卫?

参考知乎链接:https://zhuanlan.zhihu.com/p/54112006

为什么要有导航守卫?
比如在用户离开页面前怎么提醒用户,一定要离开吗?或者在页面访问前,叫用户先登录,不然不给访问,这些都用到了导航守卫。
导航守卫简单说:路由跳转是一个大的过程,这个大的过程分为跳转前中后等等细小的过程,在每一个过程中都有一函数,这些不同过程的函数能让你操作一些其他的事儿的时机,这就是导航守卫。

导航守卫分为:全局的、单个路由独享的、组件内的三种

【全局的】:是指路由实例上直接操作的钩子函数,他的特点是所有路由配置的组件都会触发,直白点就是触发任意路由就能触发这些钩子函数,钩子函数按执行顺序包括**beforeEach(全局前置守卫)、beforeResolve(2.5+)(全局解析)、afterEach(全局后置)**三个。
【beforeEach】:在路由跳转前触发。
【beforeResolve】(2.5+):这个钩子和beforeEach类似,也是路由跳转前触发。
【afterEach】:和beforeEach相反,他是在路由跳转完成后触发。

【单个路由独享的】是指在单个路由配置的时候设置,只有一个钩子函数beforeEnter。
【beforeEnter】:和beforeEach完全相同,如果全局和局部都设置,则在beforeEach之后紧随执行。

【组件内的】:是指在组件内执行的钩子函数,类似于组件内的生命周期,相当于为配置路由的组件添加的生命周期钩子函数。钩子函数按执行顺序包括beforeRouteEnter、beforeRouteUpdate (2.2+)、beforeRouteLeave三个
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值