基础

模板语法

Vue模板语法有2大类:
1.插值语法:
功能:用于解析标签体内容。
写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
2.指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)。
举例:v-bind:href=“xxx” 或 简写为 :href=“xxx”,xxx同样要写js表达式,
且可以直接读取到data中的所有属性。
备注:Vue中有很多的指令,且形式都是:v-???,此处我们只是拿v-bind举个例子。

数据绑定

Vue中有2种数据绑定的方式:
				1.单向绑定(v-bind):数据只能从data流向页面。
				2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
					备注:
							1.双向绑定一般都应用在表单类元素上(如:input、select等)
							2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。

el与data

data与el的2种写法
				1.el有2种写法
								(1).new Vue时候配置el属性。
								(2).先创建Vue实例,随后再通过vm.$mount('#root')指定el的值。
				2.data有2种写法
								(1).对象式
								(2).函数式
								如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
				3.一个重要的原则:
								由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
	-->
	<!-- 准备好一个容器-->

mvvm

MVVM模型
					1. M:模型(Model) :data中的数据
					2. V:视图(View) :模板代码
					3. VM:视图模型(ViewModel):Vue实例
		观察发现:
					1.data中所有的属性,最后都出现在了vm身上。
					2.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。

数据代理

1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性。

事件处理

基本使用

事件的基本使用:
1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
2.事件的回调需要配置在methods对象中,最终会在vm上;
3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
5.@click=“demo” 和 @click=“demo($event)” 效果一致,但后者可以传参;

事件修饰符

Vue中的事件修饰符:
					1.prevent:阻止默认事件(常用);
					2.stop:阻止事件冒泡(常用);
					3.once:事件只触发一次(常用);
					4.capture:使用事件的捕获模式;
					5.self:只有event.target是当前操作的元素时才触发事件;
					6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;

键盘事件

1.Vue中常用的按键别名:
						回车 => enter
						删除 => delete (捕获“删除”和“退格”键)
						退出 => esc
						空格 => space
						换行 => tab (特殊,必须配合keydown去使用)
						上 => up
						下 => down
						左 => left
						右 => right

			2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

			3.系统修饰键(用法特殊):ctrl、alt、shift、meta
						(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
						(2).配合keydown使用:正常触发事件。

			4.也可以使用keyCode去指定具体的按键(不推荐)

			5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

计算属性

计算属性:
1.定义:要用的属性不存在,要通过已有属性计算得来。
2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
3.get函数什么时候执行?
(1).初次读取时会执行一次。
(2).当依赖的数据发生改变时会被再次调用。
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
5.备注:
1.计算属性最终会出现在vm上,直接读取使用即可。
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
get(){
    console.log('get被调用了')
    // console.log(this) //此处的this是vm
    return this.firstName + '-' + this.lastName
},

//需要get只是计算出来的  如果需要修改就需要set  反之则不需要
//set什么时候调用? 当fullName被修改时  value就是修改的值
set(value){
    console.log('set',value)
    const arr = value.split('-')
    this.firstName = arr[0]
    this.lastName = arr[1]
     }
     
     
//简写  没有set
        fullName(){
            console.log('get被调用了')
            return this.firstName + '-' + this.lastName
        }

监听属性

监视属性watch:
1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
2.监视的属性必须存在,才能进行监视!!
3.监视的两种写法:
(1).new Vue时传入watch配置
(2).通过vm.$watch监视

//isHot就是监视的属性
vm.$watch('isHot',{
			immediate:true, //初始化时让handler调用一下
			//handler什么时候调用?当isHot发生改变时。
			handler(newValue,oldValue){
				console.log('isHot被修改了',newValue,oldValue)
			}
		})
	//配置
	watch:{
				isHot:{
					immediate:true, //初始化时让handler调用一下
					//handler什么时候调用?当isHot发生改变时。
					handler(newValue,oldValue){
						console.log('isHot被修改了',newValue,oldValue)
					}
				}
			}

深度监视

			深度监视:
					(1).Vue中的watch默认不监测对象内部值的改变(一层)。
					(2).配置deep:true可以监测对象内部值改变(多层)。
			备注:
					(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
					(2).使用watch时根据数据的具体结构,决定是否采用深度监视。
watch:{

    //正常写法
    isHot:{
         immediate:true, //初始化时让handler调用一下
         deep:true,//深度监视
        handler(newValue,oldValue){
            console.log('isHot被修改了',newValue,oldValue)
        }
    }, 
    
    //简写
     isHot(newValue,oldValue){
        console.log('isHot被修改了',newValue,oldValue,this)
    } 
}

计算属性与监听属性

computed和watch之间的区别:
					1.computed能完成的功能,watch都可以完成。
					2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
			两个重要的小原则:
						1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
						2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,
							这样this的指向才是vm 或 组件实例对象。
//监听属性

watch:{
    firstName(val){
        setTimeout(()=>{
            console.log(this)
            this.fullName = val + '-' + this.lastName
        },1000);
    },
    lastName(val){
        this.fullName = this.firstName + '-' + val
    }
}

//计算属性

fullName(){
    console.log('get被调用了')
    setTimeout(()=>{
        return this.firstName + '-' + this.lastName      //由于计算属性由return控制返回值 所以当代码执行到return时
     },1000);										//就结束了 将结果返回给了setTimeout(异步函数) 所以计算属性
}												   // 不能使用异步操作

样式绑定

绑定样式:
1. class样式
写法:class=“xxx” xxx可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
2. style样式
:style="{fontSize: xxx}“其中xxx是动态值。
:style=”[a,b]"其中a、b是样式对象。

条件渲染

1.v-if
写法:
(1).v-if=“表达式”
(2).v-else-if=“表达式”
(3).v-else=“表达式”
适用于:切换频率较低的场景。
特点:不展示的DOM元素直接被移除。
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

2.v-show
写法:v-show=“表达式”
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

列表渲染

内置指令

我们学过的指令:
v-bind : 单向绑定解析表达式, 可简写为 :xxx
v-model : 双向数据绑定
v-for : 遍历数组/对象/字符串
v-on : 绑定事件监听, 可简写为@
v-if : 条件渲染(动态控制节点是否存存在)
v-else : 条件渲染(动态控制节点是否存存在)
v-show : 条件渲染 (动态控制节点是否展示)

​ v-text指令:
​ 1.作用:向其所在的节点中渲染文本内容。
​ 2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。

​ v-html指令:
​ 1.作用:向指定节点中渲染包含html结构的内容。
​ 2.与插值语法的区别:
​ (1).v-html会替换掉节点中所有的内容,{{xx}}则不会。
​ (2).v-html可以识别html结构。
​ 3.严重注意:v-html有安全性问题!!!!
​ (1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
​ (2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!

​ v-cloak指令(没有值):
​ 1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
​ 2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。

​ v-once指令:
​ 1.v-once所在节点在初次动态渲染后,就视为静态内容了。
​ 2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

​ v-pre指令:
​ 1.跳过其所在节点的编译过程。
​ 2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

数据监视

Vue监视数据的原理:
			1. vue会监视data中所有层次的数据。

			2. 如何监测对象中的数据?
							通过setter实现监视,且要在new Vue时就传入要监测的数据。
								(1).对象中后追加的属性,Vue 默认不做响应式处理
								(2).如需给后添加的属性做响应式,请使用如下API:
												        添加位置     添加的key      添加的值
												Vue.set(target,propertyName/index,value) 或 
												vm.$set(target,propertyName/index,value)

			3. 如何监测数组中的数据?
								通过包裹数组更新元素的方法实现,本质就是做了两件事:
									(1).调用原生对应的方法对数组进行更新。
									(2).重新解析模板,进而更新页面。

			4.在Vue修改数组中的某个元素一定要用如下方法:
						1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
						2.Vue.set() 或 vm.$set()
			
			特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

收集表单数据

收集表单数据:
若:,则v-model收集的是value值,用户输入的就是value值。
若:,则v-model收集的是value值,且要给标签配置value值。
若:
1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
2.配置input的value属性:
(1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
(2)v-model的初始值是数组,那么收集的的就是value组成的数组
备注:v-model的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤

过滤器

过滤器:
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
语法:
1.注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
2.使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = “xxx | 过滤器名”
备注:
1.过滤器也可以接收额外参数、多个过滤器也可以串联
2.并没有改变原本的数据, 是产生新的对应的数据

//全局过滤器
Vue.filter('mySlice',function(value){
			return value.slice(0,4)
		})
		
	//局部过滤器  配置在methods中
    filters:{
        timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
            // console.log('@',value)
            return dayjs(value).format(str)
        }

自定义指令

需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
自定义指令总结:
一、定义语法:
(1).局部指令:
new Vue({ new Vue({
directives:{指令名:配置对象} 或 directives{指令名:回调函数}
}) })

	directives:{
				//big函数何时会被调用?1.指令与元素成功绑定时(一上来)。2.指令所在的模板被重新解析时。
				
							真实Dom   和前面的进行绑定 
				'big-number'(element,binding){
					// console.log('big')
					element.innerText = binding.value * 10
				}, 
				big(element,binding){
					console.log('big',this) //注意此处的this是window
					// console.log('big')
					element.innerText = binding.value * 10
				},
				fbind:{
				
					//指令与元素成功绑定时(一上来)
					bind(element,binding){
						element.value = binding.value
					},
					
					//指令所在元素被插入页面时
					inserted(element,binding){
						element.focus()
					},
					
					//指令所在的模板被重新解析时
					update(element,binding){
						element.value = binding.value
					}
				}
			}

​ (2).全局指令:
​ Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)

						
				//定义全局指令
		/* Vue.directive('fbind',{
			//指令与元素成功绑定时(一上来)
			bind(element,binding){
				element.value = binding.value
			},
			//指令所在元素被插入页面时
			inserted(element,binding){
				element.focus()
			},
			//指令所在的模板被重新解析时
			update(element,binding){
				element.value = binding.value
			}
		}) */

​ 二、配置对象中常用的3个回调:
​ (1).bind:指令与元素成功绑定时调用。
​ (2).inserted:指令所在元素被插入页面时调用。
​ (3).update:指令所在模板结构被重新解析时调用。

​ 三、备注:
​ 1.指令定义时不加v-,但使用时要加v-;
​ 2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

ref

ref属性

  1. 被用来给元素或子组件注册引用信息(id的替代者)
  2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
  3. 使用方式:
    1. 打标识:<h1 ref="xxx">.....</h1><School ref="xxx"></School>
    2. 获取:this.$refs.xxx
  • 通过ref标记的标签或组件会被保存在vm身上的**$refs**属性上

props

  1. 功能:让组件接收外部传过来的数据

  2. 传递数据:<Demo name="xxx"/>

  3. 接收数据:

    1. 第一种方式(只接收):props:['name']

    2. 第二种方式(限制类型):props:{name:String}

    3. 第三种方式(限制类型、限制必要性、指定默认值):

      props:{
      	name:{
      	type:String, //类型
      	required:true, //必要性
      	default:'老王' //默认值
      	}
      }
      

    备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

<Student name="李四" sex="女" :age="18"/>
这两个绑定方式差不多  加:“”里面就是js表达式的结果  所以类型就是number  不加就是string

修改数据使用data对props需要修改的东西进行接收 修改data中的值

		//修改age  通过data中的myage进行接收 不能直接修改age  去修改myage
		
		data() {
			console.log(this)
			return {
				msg:'我是一个尚硅谷的学生',
				myAge:this.age
			}
		},
		methods: {
			updateAge(){
				this.myAge++
			}
		}

扩展

  1. $data 对应的是实例身上的data _data是数据代理 提供get set
  2. 其他的都是差不多的类型
  3. props接收的参数存放在$props 通过_props进行代理到实例身上

mixin(混入)

  1. 功能:可以把多个组件共用的配置提取成一个混入对象

  2. 使用方式:

    第一步定义混合:

    1. 创建一个mixin.js文件

    2. 分别暴露
      export const hunhe = {
      	methods: {
      		showName(){
      			alert(this.name)
      		}
      	},
      	mounted() {
      		console.log('你好啊!')
      	},
      }
      export const hunhe2 = {
      	data() {
      		return {
      			x:100,
      			y:200
      		}
      	},
      }
      
      
    {
        data(){....},
        methods:{....}
        ....
    }
    

    第二步使用混入:

    全局混入:Vue.mixin(xxx)在main.js里使用
    局部混入:mixins:['xxx'] 局部引入 mixins接收 类似props

自定义插件

  1. 功能:用于增强Vue

  2. 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

  3. 在这里插入图片描述

  4. 定义插件:

    对象.install = function (Vue, options) {
        // 1. 添加全局过滤器
        Vue.filter(....)
    
        // 2. 添加全局指令
        Vue.directive(....)
    
        // 3. 配置全局混入(合)
        Vue.mixin(....)
    
        // 4. 添加实例方法
        Vue.prototype.$myMethod = function () {...}
        Vue.prototype.$myProperty = xxxx
    }
    
  5. 使用插件:Vue.use()main.js中导入插件 并通过Vue.use使用挂载插件

组件自定义事件

  1. 一种组件间通信的方式,适用于:子组件 ===> 父组件

  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。

  3. 绑定自定义事件:

    1. 第一种方式,在父组件中:<Demo @atguigu="test"/><Demo v-on:atguigu="test"/>

      1. 触发自定义事件:this.$emit('atguigu',数据)

        1. test(name,...params){
          				console.log('App收到了学生名:',name,params)
          				this.studentName = name
          			},
          			
          this.$emit('atguigu',this.name,666,888,900)
          
      2. 解绑自定义事件this.$off('atguigu')

      3. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

        1. this.$off('atguigu') //解绑一个自定义事件
          this.$off(['atguigu','demo']) //解绑多个自定义事件
          this.$off() //解绑所有的自定义事件
          
      4. 第二种方式,在父组件中:

        1. 这个方式要当组件挂载完毕之后才可以去获取 灵活性强可以对绑定事件前进行异步操作
      5. <Demo ref="demo"/>
        ......
        mounted(){
           this.$refs.demo.$on('atguigu',回调)
        }
        
      6. 三 通过props

      7. <School :getSchoolName="getSchoolName"/>
        
        props:['getSchoolName'],
        
    2. 组件上也可以绑定原生DOM事件,需要使用native修饰符。

      1. 直接给Student绑定一个原生的点击事件

      2. <Student ref="student" @click.native="show"/>
        
    3. 注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

全局事件总线

  1. 一种组件间通信的方式,适用于任意组件间通信。

  2. 安装全局事件总线:

    new Vue({
    	......
    	beforeCreate() {
    		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
    	},
        ......
    }) 
    
  3. 使用事件总线:

    1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。

      mounted() {
      	this.$bus.$on('hello',(data)=>{
          console.log('我是School组件,收到了数据',data)
      })	
      
    2. 提供数据:this.$bus.$emit('xxxx',传递数据)

      data() {
              return {
                  name:'张三',
                  sex:'男',
              }
          },
      methods: {
      	sendStudentName(){
          this.$bus.$emit('hello',this.name)
      }
      
  4. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

消息订阅与发布

  1. 一种组件间通信的方式,适用于任意组件间通信。

  2. 使用步骤:

    1. 安装pubsub:npm i pubsub-js

    2. 引入: import pubsub from 'pubsub-js'

    3. 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

      this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
                  console.log(this)
                  // console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
              })
          },
          beforeDestroy() {
              // this.$bus.$off('hello')
              pubsub.unsubscribe(this.pubId)   //取消订阅
          },
      
    4. 提供数据:pubsub.publish('xxx',数据)

    sendStudentName(){
        // 类似 this.$bus.$emit('hello',this.name)
        pubsub.publish('hello',666)             //发布消息
    }
    
    1. 最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

nextTick

  1. 语法:this.$nextTick(回调函数)
  2. 作用:在下一次 DOM 更新结束后执行其指定的回调。
  3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

插槽

  1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件

  2. 分类:默认插槽、具名插槽、作用域插槽

    1. 默认插槽:

      父组件中:
              <Category>
                 <div>html结构1</div>
              </Category>
      子组件中:
              <template>
                  <div>
                     <!-- 定义插槽 -->
                     <slot>插槽默认内容...</slot>
                  </div>
              </template>
      
      • ​ 当父组件使用子组件里有多个根节点时,会把所有根节点当做一个节点插入,要实现指定插入使用具名插槽,就只是多指定一个name属性
      1. 具名插槽:

        父组件中:
                <Category>
                    <template slot="center">
        				<div>html结构1</div>    //单个结构可以不使用template 直接使用<div slot='center'></div>
                    </template>
        
                    <template v-slot:footer>      //v-slot与slot 只是方法的新与旧 都可以使用
                       <div>html结构2</div>
                    </template>
                </Category>
        子组件中:
                <template>
                    <div>
                       <!-- 定义插槽 -->
                       <slot name="center">插槽默认内容...</slot>
                       <slot name="footer">插槽默认内容...</slot>
                    </div>
                </template>
        
        
  3. 作用域插槽:

    1. 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)

    2. 使用 绑定自身的数据 在使用方可以通过

      1. 获取

        这两个也是方法新旧的 都可以使用

      2. 必须使用template进行接收 接收的是一个对象需要scopeData.games获取数据

    3. 具体编码:

      父组件中:
      		<Category>
      			<template scope="scopeData">
      				<!-- 生成的是ul列表 -->
      				<ul>
      					<li v-for="g in scopeData.games" :key="g">{{g}}</li>
      				</ul>
      			</template>
      		</Category>
      
      		<Category>
      			<template slot-scope="scopeData">
      				<!-- 生成的是h4标题 -->
      				<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
      			</template>
      		</Category>
      子组件中:
              <template>
                  <div>
                      <slot :games="games"></slot>
                  </div>
              </template>
      		
              <script>
                  export default {
                      name:'Category',
                      props:['title'],
                      //数据在子组件自身
                      data() {
                          return {
                              games:['红色警戒','穿越火线','劲舞团','超级玛丽']
                          }
                      },
                  }
              </script>
      

动画

  • 过度类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hht8RLnp-1660566003942)(C:\Users\sxf\AppData\Roaming\Typora\typora-user-images\image-20220529143047254.png)]

transition组件

  • 使用此组件包裹需要实现动画效果的东西 只能包裹一个组件

  • 两个属性 name(可省略) appear(默认false)

  • 指定name属性 则为自定义类名(优先级高)

    • 指定name属性后过度类型则变为name-enter
    • appear开启初始渲染动画 也可单独添加渲染效果设置
      • appear-class(初始的class样式)
      • appear-active-class(整个过程的样式)
      • appear-to-class (结束的样式)
  • <transition name="hello" appear>
    	<h1 v-show="isShow">你好啊!</h1>
    </transition>
    
  • 				方式一  借助keyframse动画实现
    /* 初始状态 */
    	h1{
    		background-color: orange;
    	}
    
    	/* 开始样式 */
    	.hello-enter-active{
    		animation: atguigu 0.5s linear;
    	}
    
    	/* 结束样式 */
    	.hello-leave-active{
    		animation: atguigu 0.5s linear reverse;
    	}
    
    	/* 动画效果 */
    	@keyframes atguigu {
    		from{
    			transform: translateX(-100%);
    		}
    		to{
    			transform: translateX(0px);
    		}
    	}
    	
    										方式二  过渡
    		h1{
    		background-color: orange;
    	}
    	
    	/* 进入的起点、离开的终点 */
    	.hello-enter,.hello-leave-to{
    		transform: translateX(-100%);
    	}
    	
    	/* 动画过程 */
    	.hello-enter-active,.hello-leave-active{
    		transition: 0.5s linear;
    	}
    	
    	/* 进入的终点、离开的起点 */
    	.hello-enter-to,.hello-leave{
    		transform: translateX(0);
    	}									
    

transition-group组件

  1. 可以包裹多组件 使用方法与上一致
  2. 需要指定key值

animate.css

  • 动画库

  • <transition-group 
    			appear
    			//配置动画库
    			name="animate__animated animate__bounce" 
    			//开始动画
    			enter-active-class="animate__swing"
    			//结束动画
    			leave-active-class="animate__backOutUp"
    		>
    			<h1 v-show="!isShow" key="1">你好啊!</h1>
    			<h1 v-show="isShow" key="2">尚硅谷!</h1>
    		</transition-group>
    

css3动画

配置代理

原因:违背了同源策列

  • 代理服务器的端口和本身是一样的

  • 在发请求时 请求是转发给代理服务器 首先会先判断自身有没有 如果有就不会发给代理服务器了

  • 代理服务器配置接收到请求转发的地址 可配置请求前缀开启多个代理

    • axios.get('http://localhost:8080/students').then(
      					response => {
      						console.log('请求成功了',response.data)
      					},
      					error => {
      						console.log('请求失败了',error.message)
      					}
      
      • //开启代理服务器(方式一)
        module.exports = {	
        	devServer: {
            	proxy: 'http://localhost:5000'
         	 }
          }
          
          缺点:不能配置多个代理
        
      • axios.get('http://localhost:8080/demo/students').then(
        					response => {
        						console.log('请求成功了',response.data)
        					},
        					error => {
        						console.log('请求失败了',error.message)
        					}
        
        //开启代理服务器(方式二)
        	devServer: {
            proxy: {
              '/atguigu': {
                target: 'http://localhost:5000',
        				pathRewrite:{'^/atguigu':''}, //重写路径 去除前缀在发过去
                // ws: true, //用于支持websocket
                // changeOrigin: true //用于控制请求头中的host值
              },
              '/demo': {
                target: 'http://localhost:5001',
        				pathRewrite:{'^/demo':''},
                // ws: true, //用于支持websocket
                // changeOrigin: true //用于控制请求头中的host值
              }
            }
          }
        
        • changeOrigin
          • 默认true 用于代理服务器如实告诉接收请求方自己请求的地址
          • 就是骗不骗人 true骗 收到的请求是和自己一样的
          • false 就如实显示发请求的地址

路由router

编程式导航

基本使用

  1. 使用<router-view>进行占位

  2. <router-link to=""> 链接跳转

  3. 配置路由

    const routes = [
    	{
    		path:'/',
    		redirect:'/Nav'  重定向 当访问/或初次加载时访问
    	},
    	{
    	path:'/Gengduo',
    	component:Gengduo
    	}
    	{
    	path:'/Nav',
    	component:Nav,
    	children:[          子路由
    		{
    				path:'/',
    				redirect:'Home'
    		},
    		{
    			path:'Mine',
    			component:Mine
    		}
    	]
    }
    ]
    

$route

params :id

动态路由就是增加了一个传参

this当前组件实例 存在许多方法 可自行查看

<router-link to="/ss/1" >   传参

{
path:"/ss:id"     通过冒号id进行设置
}


this.$route.params.id  通过这个进行获取


也可以为跳转链接 添加props=true吗 也可以在路由规则里添加  开启props传参
获取时就直接通过props获取

路由的props配置

作用:让路由组件更方便的收到参数
{
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
	// props:{a:900}

	//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
	// props:true
	
	//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件   处理query参数
	props(route){					可以使用解构或者连续解构
		return {
			id:route.query.id,
			title:route.query.title
		}
	}
}

声明式导航

$router

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

  • 通过触发事件来进行跳转 参数可以通过加号来连接

    this.$router.push('/movie'+id)   
    

    在路由规则里为相应的路由设置name属性

在这里插入图片描述

导航守卫

在路由js文件中设置

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

vuex

state

  • 提供唯一的公共数据源,所有的共享数据统一放在Store的State进行存储

  • 两种访问方式

    1.this.$Store.state.全局数据名称
    2.从vuex中导入mapState函数
    
    	import {mapState} from 'vuex'
    	在将全局属性映射为当前组件的计算机属性
    	
    	//...为展开运算符
    	computed:{
    		...mapState(['数据名'])
    		或者 
    	}
    	
    			//借助mapState生成计算属性,从state中读取数据。(对象写法)
    			// ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),
    
    			//借助mapState生成计算属性,从state中读取数据。(数组写法)
    			...mapState(['sum','school','subject']),
    

Mutation

  • 用于变更Store中的数据 只能通过Mtation进行变更 不能直接操作Store
  • 不要在mutation中执行异步操作
state  为vuex的Store实例  第二个参数为模块调用该方法时传入的参数 
mutation:{
	addN(state,step){}  定义方法来进行变更
}
  • 两种触发方式

    1.this.$store.commit('调用的方法',传入参数)
    2.从vuex导入mapMutation
    
    	import {mapMutation} from 'vuex'
    	将需要的mutations函数映射为当前组件的methedss方法
    	
    	metheds:{
    		...mapMutation(['方法1','方法2'])
    	}
    

Action

  • 用于执行异步操作 要通过Mutation的方式更变数据
actions:{
	addNas('context',参数){}
}

// 第一个参数必定为context  他拥有和Store相同的属性和方法

在这里插入图片描述

  • 两种触发方式

    1.this.$store.dispath('addNas',参数)
    2.导入mapAction 
    
    	import {mapAction} from 'vuex'
    	将指定的action方法映射为当前组件方法
    	
    	methods:{
    		...mapAtion(['方法','方法'])
    	}
    
  • 与Mutation结合使用

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

在actions中使用context调用commit方法与Mutation结合

Getter

  • 用于对Store中的数据进行加工处理形成新的数据不会改变原数据,只起到一个包装的作用,类似于vue的计算属性

    这个参数state就是vuex的state  ss为state的数据
    gets1为包装后的*新数据*
    getters:{
    	gets1:state=>{
    		return '当前最新数据是【'+state.ss+'】'
    	}
    }
    
    • 两种调用方式
    1.this.$store.getter.名称
    2.导入mapGetter
    
    	import {mapGetter} from 'vuex'
    	
    	将要用到的属性映射为当前组件的计算机属性
    	
    	computed:{
    		...mapGtter(['属性名','属性名'])
    	}
    

mudules

  • 可以让每一个模块拥有自己的store(state、mutation、action、getter),使结构清晰,方便管理
  • 如果所有的状态管理都写在同一个store,会非常臃肿
//一个模板store
const moduleA = {
  state:{
    name:"Rick"
  },
  mutations:{
    moduleAupdname(state){
      state.name = "Liu"
    }
  },
  getters:{

  },
  actions:{

  }
}

//vuex主store  在modules进行注册命名
const store = new Vuex.Store({
	state:{
	   
	},
	mutations:{
	
	},
	getters:{
	
	},
	actions:{
	
	},
	modules:{
		a:moduleA       《================
	}
})

在调用时方法一样的

this.$store.a.state.属性   这里的a是选择模板的命名 指定去寻找相应的模板的属性   a也可以省略  省略后 后先去寻找主模板  找不到就按去寻找子模板

namespaced命名空间

在这里插入图片描述

  1. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    
  2. 开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    
  3. 开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  4. 开启命名空间后,组件中调用commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    

总结

img

Promise

概念

Promise是异步编程的一种解决方案,其实是一个构造函数,自己身上有all reject resolve 几个方法,原型上有then catch

几个特点

//Promise的两个参数

new Promise(function(resolve,reject){
		resolve('要返回的数据可以是任何数据 例如接口数据')  成功调用方法
		reject('数组不够')								失败调用回方法
}).then(成功时回调function(data){},失败时回调function(){})    data成功接受的数值
.catch((reason)=>{										
		console.log(reason)								reason失败原因
})

Promise.all([f,f]).then(成功回调function(results){
	console.log(results)
})		

all接受一个数组为所有需要异步的Promise的对象  (创建几个加几个所以成功才会回调)
results all会把所以成功的回调传给then  通过then的成功回调将所有结果进行打包成一个数组

Promise.race([f,f]).then(成功失败回调()=>{})     赛跑  谁先执行完就谁用回调 其余不行   也可以让所有f进行异步

  1. 对象状态不受外界影响,Promise对象代表一个异步操作,有三个状态
    • pending (进行中)
    • fulfilled (已成功)
    • rejected (已失败)
    • 只有异步操作的结果决定这三个状态 任何其他操作都无法改变
  2. 一旦状态改变,就不会在变,任何时候都可以得到这个结果 Promise对象状态改变只有两种可能
    • pending 到 fulfilled
    • pending 到 rejected
    • 只要发生一种 状态就不会改变 这个时候称之为resolved(已定型)
  3. 我们new一个Promise对象 没有调用他 当我们传进去函数就已经执行了 在使用时一般包在一个函数里 等待函数调用触发
  4. 传入的函数会返回一个Promise对象

then

  • then() 和我们使用的回调函数差不多 他可以接受一个参数 是接受resolve(或reject返回的错误原因)返回的数据这时就返回了‘要返回的数据可以是任何数据 例如接口数据’
  • 可以连续.then() (链式编程) 因为Promise每次都会返回一个新的Promise对象

catch

与try catch类似 用来捕获异常

all()

他提供了异步操作的能力,Promise方法(Promise.all()执行) 通过调用他将所以操作进行异步 在所有都成功时才回调

all接受一个数组为所有需要异步的Promise的对象 (创建几个加几个所以成功才会回调)
results all会把所以成功的回调传给then 通过then的成功回调将所有结果进行打包成一个数组

rece

这个是 谁先执行完就执行then 类似与赛跑机制 不管是成功回调还是失败回调 其余的都不会在进入race任何回调 会进行异步执行 执行自己的方法进行返回

Axios

简介

axios框架全称 (Ajax I/O system)

  • 基于promise用于浏览器和node.js的http客户端,因此可以使用PromiseAPI

请求方式

  1. get 获取数据,请求指定信息,返回实体对象
  2. post 向指定资源提交数据
  3. put 更新数据,从客户端向服务器传送数据取代指定的文档的内容
  4. path 更新数据,是对put方法的补充,用来对已知资源进行局部更新
  5. delete 请求服务器删除指定数据

get

方法一
this.$axios.get('/goods.json',{
	parms:{
		id:1							parms  为请求的地址后的参数  也可要直接写在url中 /goods.json?id=1
	}
}).then(res=>{
	console.log(res.data)
},err=>{
	console.log(err)
})

方法二
this.$axios({
	method:'get',
	url:'/goods.json',
	parms:{
		id:1
	}
}).then()

post

  • post请求分为两种类型
    • form-data 表单提交,图片上传,文件上传,用这个比较多
    • application/json 一般用于Ajax异步请求
    • params是添加到url的请求字符串中的,用于get请求。
      data是添加到请求体(body)中的, 用于post请求。

application/json 请求

方法一
this.$axios.post('/url',{
	id:1
}).then(res=>{
	console.log(res.data)
},err=>{})

方法二
this.$axios({
	method:'post',
	url:'/url',
	data:{
		id:1                              请求的参数  get是带在url上是请求路径  post是请求体 url不带参数 用data
	}
}).then()

form-data 请求 提交表单数据

let data = {
	请求参数
}

let formdata = new FormData();

for(let key in data){
	fromdata.append(key,data[key])
}

this.$axios.post('/good.json',fordata).then()   将上传数据封装到formdata中  进行请求提交

put path

put请求

this.$axios.put('/url',{
	id:1
}).then()

path请求

this.$axios.path('/url',{
	id:1
}).then()

delete

参数以明文形式提交

this.$axios.delete('/url',{
	params:{
		id:1
	}
}).then

参数以封装对象形式提交

this.$axios.delete('/url',{
	data:{
		id:1
	}
}).then()


方法二
axios({
	method:'delete',
	url:'/url',
	params:{         明文形式提交
		id:1
	},
	data:{
		id:1         封装对象形式提交
	}
}).then()

all

  • 并发请求

  • 同时进行多个请求,并统一处理返回值

  • 发送多个请求(并发请求),类似于promise.all,若一个请求出错,那就会停止请求

this.$axios.all([---------------------------------------------
	this.$axios.get(/g1.json),
	this.$axios.get(/g2.json)
]).then(-------------------------------------------------------
	this.$axios.spread((g1,g2)=>{      spread  成功时的处理   失败会停止请求
		console.log(g1.data)
		console.log(g2.data)
	})
)

axios实例

创建axios实例

通过create创建axios实例 并取名字

  • baseURL 请求的域名,基本地址,类型:String
  • timeout 请求超时时长,单位ms,类型:Number
  • url 请求路径,类型:String
  • method 请求方法,类型:String
  • headers 设置请求头,类型:Object
  • params 请求参数,将参数拼接在URL上,类型:Object
  • data 请求参数,将参数放到请求体中,类型:Object
let instance = this.$axios.create({
				baseURL: 'http://localhost:9090',
				timeout: 2000
			})
			
instance.get('/goods.json').then(res=>{
	console.log(res.data);
})
————————————————
版权声明:本文为CSDN博主「柠檬树上柠檬果柠檬树下你和我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39765048/article/details/117688019

axios全局配置

示例代码

//配置全局的超时时长
this.$axios.defaults.timeout = 2000;					default设置默认属性
//配置全局的基本URL
this.$axios.defaults.baseURL = 'http://localhost:8080';

axios实例配置

示例代码

let instance = this.$axios.create();
instance.defaults.timeout = 3000;

axios请求配置

this.$axios.get('/goods.json',{
				timeout: 3000
			}).then()

以上配置的优先级为:请求配置 > 实例配置 > 全局配置

拦截器

拦截器:在请求或响应被处理前拦截它们

1、请求拦截器

this.$axios.interceptors.request.use(config=>{
				// 发生请求前的处理
       			 return config
		},err=>{
			// 请求错误处理
			return Promise.reject(err);
		})
		
		//或者用axios实例创建拦截器
        let instance = $axios.create();
        instance.interceptors.request.use(config=>{
            return config
        })

2、响应拦截器

示例代码

this.$axios.interceptors.response.use(res=>{
							//请求成功对响应数据做处理
		return res 			//该返回对象会传到请求方法的响应对象中
		},err=>{
			// 响应错误处理
			return Promise.reject(err);
})

3、取消拦截

let instance = this.$axios.interceptors.request.use(config=>{
				config.headers = {
					token: ''
				}
				return config
			})
			
//取消拦截
this.$axios.interceptors.request.eject(instance);

4、错误处理

示例代码

this.$axios.get('/url').then(res=>{

		}).catch(err=>{
			//请求拦截器和响应拦截器抛出错误时,返回的err对象会传给当前函数的err对象
			console.log(err);
})

5、取消请求

let source = this.$axios.CancelToken.source();

this.$axios.get('/goods.json',{
				cancelToken: source
			}).then(res=>{
				console.log(res)
			}).catch(err=>{
				//取消请求后会执行该方法
				console.log(err)
			})

//取消请求,参数可选,该参数信息会发送到请求的catch中
source.cancel('取消后的信息');

原型与原型链

图解

img

原型概念

img

新对象在原型的基础之上建立起来 同时也会继承原型的相应属性和方法

prototype

  • 原型的意思 通过函数的方式创建obj对象 此函数可以调用proto来获取对象的原型

  • 对象obj没有这个 属性

_proto_

  • 每个对象都会有这个属性 用来指向该对象的原型

construction

  • 每一个原型都有construction属性 用来指向关联的构造函数
  • 同时对象继承原型,也会拥有这个方法 指向构造函数

总结 实例与原型

当读取实例对象的属性时,如果没有找到则会找他的原型,还没有,就原型的原型,一直到最顶层

通过这样的一层层关系 组成了原型链

Logo

前往低代码交流专区

更多推荐