Vue学习

vue

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

Vue的基础原理:拦截

利用了Object.definedProperty方法进行拦截

var obox=document.getElementById("box");
        Object.defineProperty(obj,"myname",{
        //获取元素则执行
            get(){
                return obox.innerHTML
            },
           //修改元素则执行
            set(value){
                console.log("set",value)
                obox.innerHTML=value
            }
        })

注意:vue3的变化

Object.defineProperty有以下缺点。
1、无法监听es6的Set、Map变化;
2、无法监听Class类型的数据;
3、属性的新加或者删除也无法监听;
4、数组元素的增加和删除也无法监听。
针对Object.defineProperty的缺点,ES6Proxy都能够完美得解决,它唯一的缺点就是,对IE不友好,所以vue3在检测到如果是使用IE的情况下(没错,IE11都不支持Proxy)

模板语法

切换样式:

 <style>
        .red{
            background-color: red;
        }
        .yellow{
            background-color: yellow;
        }
    </style>
</head>
<body>
    <div id="box">
        {{myname}}-{{myage}}
        <div :class="isColor?'red':'yellow'">换背景颜色</div>
        <button @click="handleChange()">change</button>
    </div>
    <script>
       new Vue({
        el:"#box",
        data:{
            myname:"xiaoming",
            myage:12,
            
            isColor:true
        },
        methods:{
            handleChange(){
                this.myname="hong",
                this.myage=100
                
                this.isColor=!this.isColor

            }
        }
       })
    </script>
  • 表达式
    指令:是带有v-前缀的特殊属性
    v-bind 动态绑定属性
    v-if 动态创建/删除,用来控制切换元素是否显示或隐藏类似if,还有v-else,v-else-if一般情况下一起使用
    v-show 动态显示/隐藏
    v-on 绑定事件
    v-for 遍历,用来渲染列表,语法:v-for=“(item,index) in/of data”
    v-model 双向绑定表单
    v-html 针对纯HTML,将标签元素的效果展示。

缩写:
v-bind:src ->:src
v-on:click ->@click

todolist

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../code/lib/vue.js"></script>
</head>
<body>
    <div id="box">
        <input type="text" v-model="mytext"/>
        <button @click="handleAdd()"></button>
        <ul v-show="datalist.length">
            <li v-for="(data,index) in datalist">
                {{data}}
                <button @click="handleDel(index)">del</button>
            </li>
        </ul>
        <div v-show="!detalist.length">daiban</div>
</div>
    <script>
        var vm= new Vue({
            el:"#box",
            data:{
                datalist:["111","222","333"],
                mytext:"aaa"
            },
            methods:{
                handleAdd(){
                    this.datalist.push(this.mytext)
                    this.mytext=""
                },
                handleDel(index){
                    this.datalist.splice(index,1)
                }
            }


        })
    </script>
</body>
</html>

点击变色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../code/lib/vue.js"></script>
    <style>
        .active{
            background-color: red;
        }
    </style>
</head>
<body>
    <div id="box">
        <ul>
            <li v-for="(data,index) in datalist" :class="current===index?'active':''" @click="handleClick(index)">
                {{data}}
            </li>
        </ul>
    </div>
    <script>
        new Vue({
            el:"#box",
            data:{
                datalist:["1","2","3"],
                current:0
            },
            methods:{
                handleClick(index){
                    this.current=index
                }
            }
        })
    </script>
</body>
</html>

class与style

  • vue2
    不支持动态增加属性的拦截
    解决方案:Vue.set(obj,属性,true)
  • Vue3
    支持动态增加属性的拦截
    Vue3语法:Vue.createApp(obj).mout("#box") || Vue.createApp({ }).mout("#box")

列表渲染

列表的渲染一般情况下,基本原理是使用了虚拟建立的DOM节点

  • key
    跟踪每一个节点,从而重用和重排现有元素,减少空间时间浪费
    一般创建列表是建议都加上key值:id , data.id
  • 数组更新检测

a.使用以下方法操作数组,可以检测变动
push()、 pop() 、shift()、 unshift、 splice()、sort() 、reverse()

b.filter(),concat()和 slice() ,map),新数组替换旧数组

c.能检测以下变动的数组
vm.items[indexOfltem]=newValue

  • 解决

(1)Vue.set(example1.items, indexOfltem,newValue)
(2)splice

  • 应用:显示过滤结果

事件处理

(1)监听事件-直接触发代码
(2)方法事件处理器-写函数名handleClick
(3)内联处理器方法-执行函数表达式handleClick($event) $event事件对象
(4)事件修饰符https://cn.vuejs.org/v2/guide/events.html
.stop 防止事件冒泡,加在子元素上
.prevent
.capture
.self 防止事件冒泡,加在父元素上
.once

计算属性和监听器(watch)

  1. data -> 状态,被拦截。
  2. 方法 ->事件绑定,逻辑运算,可以不用return,没有缓存,每次相同调用,都要执行一次
  3. 计算属性(重视结果)->解决模板过重的问题,必须有return,只求结果,有缓存,同步,每次相同调用,只执行一次
  4. watch(重视过程),监听一个值的改变。不用返回值,异步同步。

fetch

用法:

fetch("...").then(res=>res.json()).then(res=>...)

get url路径 ?name=...&age=...
post body请求体
(1) x-www-formurlencoded,name=...&age=... (2json, ·{"name":"..."&...}·)

axios

先引入相关文件

语法:

axios.post("***","name=...&age=...")
axios.post("***",{name:"..."&...})
axios.get("")

工厂过滤器

<img :src="item.img | imgFilter1 | imgFilter2">
<script>
Vue.filter("imgFilter1",(url)=>{
return url.replace('w.h/','')})
Vue.filter("imgFilter2",(url)=>{
return url+'@......'})
</script>

组件

1.起名字:js驼峰,html 链接符-
2.dom片段 没有代码提示 没有高亮显示-vue单文件组件解决
3.css 只能写成 行内。-vue单文件组件解决
4. template 包含一个根节点
5.组件是孤岛,无法【直接】访问外面的组件的状态或者方法。-间接的组件信来交流。
6.自定义的组件 data 必须是一个函数,
7.所有的组件都在一起, 太乱了 — vue单文件组件解决

语法:

//全局定义
Vue.component("navbar",{
template:`自定义组件元素及样式,不能并列组件,只能嵌套`,
//自定义的属性及方法,只能在封装块中定义。
methods:{
自定义组件绑定的方法
},
//data必须是函数
data(){}

})
//局部定义
Vue.component("navbar",{
template:`自定义组件元素及样式+子定义组件元素`,
//自定义的属性及方法,只能在封装块中定义。
methods:{
自定义组件绑定的方法
},
//data必须是函数
data(){}
components:{
	自定义子组件,创建语法与前面一致。
}
})
父传子
<div>
<navbar myname="..." :myright="..."></navbar>
<div>
<script>
Vue.component("navbar",{
//第一种方式:props:["myname","myright"],//接受定义的属性
//第二种
props:{
	myname:{
	type:String,
	default:""
	},
	myright:{
	type:Boolean,
	default:true
	}
		
}
template:`自定义组件元素及样式,不能并列组件,只能嵌套`,
//自定义的属性及方法,只能在封装块中定义。
methods:{
自定义组件绑定的方法
},
//data必须是函数
data(){}

})
</script>
子传父

在父组件的子组件上定义一个方法用@myevent(方法名)="函数",挂载子组件传递过来的参数,然后在子组件中,通过this.$emit("方法名",数据)来传送

在调用方法时,
若在子组件传入数据this.$emit("方法名",data(数据))
会默认传递一个形参
方法名(data){console.log(data)},并接受

中间人模式(兄弟传值或复杂关系传值)

第一种方法:通过本身先传值给父级元素,父级组件再将数据传入另一个等级组件种,再然后通过关系一步步传入。

第二种方法:利用ref直接绑定DOM,拿到的就是dom对象,绑定组件,就是组件对象,接着直接通过this.$ref.属性名直接获取,并传入,但是不推荐大量使用。

bus

订阅发布模式

var bus=new Vue()

中央事件总线:
事件监视:bus.$on("自定义事件名称",要获取的数据)->接收数据,给接受数据的组件绑定,一般在mounted中
事件发送:bus.$emit("自定义事件名称",接收数据想要的数据)->发送数据

动态组件
  • <component>元素,动态地绑定多个组件到它的is属性
//若变量符合条件则显示相应的组件
<component is="wihch(变量)"></component>
  • <keep-alive>保留状态,避免重新渲染
slot插槽
  • 混合父组件的内容与子组件自己的模板–>内容分发
  • 父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译

案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../code/lib/vue.js"></script>
</head>
<body>
    <div id="box">
        <navbar>
            <button @click="isShow=!isShow">click</button>//对应slot
        </navbar>
        <slidebar v-show="isShow"></slidebar>
    </div>
    <script>
        Vue.component("navbar",{
            template:
            `
                <div>
                    <slot></slot>    
                </div>
            `
        })
        Vue.component("slidebar",{
            template:
            `
                <ul>
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                </ul>
            `
        })
        new Vue({
            el:"#box",
            data:{
                isShow:false
            }
        })
    </script>
</body>
</html>

注意:v-slot只能添加在template上

trsnsition过渡

多元素过渡时,相同等级及相同标签名的,须要添加key值
案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../code/lib/vue.js"></script>
    <style>
        .a-enter-active{
            animation: ccc 1s ;
        }
        .a-leave-active{
            animation: ccc 1s reverse;
        }
        @keyframes ccc {
            0%{
                opacity: 0;
                transform: translateX(100px);
            }
            100%{
                opacity: 1;
                transform: translateX(0px);
            }
        }
    </style>
</head>
<body>
    <div id="box">
        <input type="text" v-model="mytext"/>
        <button @click="handleAdd()">add</button>
        //多个组件(列表过渡)
        <transition-group name="a" tag="ul" v-show="datalist" mode="out-in\(in-out)"显示方式:先加后删或相反>
            <li v-for="(data,index) in datalist" :key="data">
                {{data}}
                <button @click="handleDel(index)">del</button>
            </li>
        </transition-group>
        <div v-show="!datalist.length">daiban</div>
</div>
    <script>
        var vm= new Vue({
            el:"#box",
            data:{
                datalist:["111","222","333"],
                mytext:"aaa"
            },
            methods:{
                handleAdd(){
                    this.datalist.push(this.mytext)
                    this.mytext=""
                },
                handleDel(index){
                    this.datalist.splice(index,1)
                }
            }


        })
    </script>
</body>
</html>
虚拟dom的diff方式

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

生命周期

在这里插入图片描述

swiper学习

https://www.swiper.com.cn/

Vue3组件
var app=Vue.createApp()
//定义新组件
Vue.component("couter",{
	//data必须声明为一个返回一个初始数据对象的函数
	data:function(){
		return ...
	},
	template:`组件布局`
})

指令

  1. 自定义指令
<div id="box">
        <div v-hello="'red'">11111</div>
    </div>
    <script>
        Vue.directive("hello",{
            inserted(el,binding){
                console.log(binding)
                el.style.backgroundColor=binding.value
                //el:插入元素节点
                //binding节点的属性
                //binding.value为red
            }
        })
        new Vue({
            el:"#box",
            data:{

            }
        })
})
  1. 钩子函数
  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新(详细的钩子函数参数见下)。
  • componentUpdated:指令所在组件的VNode及其子VNode全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。
  1. nextTick
    比updated执行还要晚,只执行一次
    一般用在轮播插入最后一个元素后再进行,但是不建议,易出现bug

单文件组件

vue-cli

  • npm install -g @vue/cli (一次安装)
  • +vue create myapp
  • npm run serve 开发环境构建
  • npm run build 生产环境构建
  • npm run lint 代码检测工具
  • style标签 加上scoped属性,css局部生效 style标签 加上lang=\"scss\",支持scss

proxy代理

在vue.config.js中配置
反向代理

devServer:{
	port: ,//
	proxy:{
		'/xiao':{
			target:'htpp://...',
			changeOrigin:true,
			pathRewrite:{
					'^/xiao':''//将不同的数据,但是名字重复的重新设置名子的,重新改为原来的样子。
				}
			
		}
	}
}

路由器

  • (1)hash路由 > location.hash 切换
    window.onhashchange 监听路径的切换
  • (2)history路由> history.pushState 切换
    window.onpopstate 监听路径的切换
<router-view></router-view>//路由容器
  • router/index.js
Vue.use(VueRouter)// 注册路由插件
// 配置表
const routes = [
  {
    path: '/films',
    component: Films,
    //嵌套路由
    children:[
      {
        path:'/films/nowplaying',
        component:Nowplaying
      }
    ]
  },
  {
	path:'/center',
	component:()=>import('@/views/Center'),//懒加载,防止在主页时加载时间过长
	meta:{
		isrequired:true
	}
	}
  {
    path: '/cinemas',
    component: Cinemas
  },
  {
    path: '/center',
    component: Center
  },
  // 重定向
  {
    path: '*',
    redirect: '/films'
  }{
    name: 'xiaoDetail', // 命名路由
    path: '/detail:id', // 动态路由
    component: Detail
  }

导航

  • 声明式导航
	  <!-- 声明式导航 -->
      <!--vue 4 写法 -->
      <router-link to="/films" custom v-slot="{navigate,isActive}" >
        <li @click="navigate" :class="isActive?'xiaoming':''">电影</li>
      </router-link>
      <!--vue 3之前 及3 写法-->
      <router-link to="/cinemas" active-class="xiaoming" tag="li">影院</router-link>
  • 编程式导航
<template>
    <div>
        nowplaying
        <ul>
            <li v-for="data in datalist" :key="data" @click="handleChangePage(data)">
                {{data}}
            </li>
       </ul>
    </div>
</template>

export default {
  data () {
    return {
      datalist: ['111', '222', '333']
    }
  },
  methods: {
    // 编程式导航
    handleChangePage (id) {
      // 1.通过路径跳转
      // this.$router.push(`/detail/${id}`)
      // 2.通过命名路由跳转
      this.$router.push({
        name: 'xiaoDetail',
        params: {
          id
        }
      })
    }//全局式拦截
    router.beforeEach((to,from,next)=>{
		if(to.meta.isrequired)
		{
			//判断是否含有token
			if(localStorage.getItem('token'))
			{
				next()//有就跳转页面
			}else
			{
				next('/login')//没有就拦截
			}
		}else
		{
			next()
		}

	})
  }
}

rem布局复习

document.documentElement.style.fontSize=document.documentElement.clientWidth/(设计稿宽度)*100+'px'

axios初次封装

//内封装http.js
import axios from 'axios'
const http =axios.create({
baseURL:'',
timeout:10000,
headers:{

}
})
export default http



//外使用,应用在不同的组件文件中
import http form 'axios文件地址'
export default{
data(){
	return {

	}
},
mouted(){
	http({
		url:'获取内容的地址'headers:{

		}

	}).then(res=>{})
}

}

axios拦截

本课程主要用该方式,对加载动画进行添加和删除。

// Add a request interceptor --在发送请求之前拦截 ->showLoading
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  },
   function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor --在成功后拦截 -- hideLoading
axios.interceptors.response.use(function (response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response;
  }, 
  function (error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
    return Promise.reject(error);
  });

饿了吗组件库和vant组件库

https://element.eleme.cn/#/zh-CN

http://vant3.uihtm.com/#/zh-CN

Vuex

Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.

在这里插入图片描述

//新创建一个store文件夹,其中放入带有vuex的index.js的文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
	//state公共状态,传入公共数据
	state:{
		
	},
	//统一管理,被devtools 记录状态的修改
	//只能支持同步
	//是对状态的追踪,而非改变
	//改变状态在methods中进行
	mutations:{
	
	},
	//Action 类似于 mutation,不同在于:
	//Action 提交的是 mutation,而不是直接变更状态。
	//Action 可以包含任意异步操作。
	actions:{

	}

})
  • 可以用辅助函数来减少重复的this.$store.—

mapState、mapActions、mapMutations

//在需要使用的组件文件中引入
import {mapState、mapActions、mapMutations} from 'vuex'
export default {
	component:{
		...mapState[{'title'}]//与this.$store.title一样
	},
	methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
	}	
}

git

基础使用方法 -->git–菜鸟教程

经典web服务器nginx介绍

Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。

  • (1)正向代理
    正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。

  • (2) 反向代理\n\n客户端是无感知代理的存在的,反向代理对外都是透明的,访问者并不知道自己访问的是一个代理。因为客户端不需要任何配置就可以访问。
    反向代理,“它代理的是服务端”,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。

  • nginx的基础配置(代理等)

nginx -c kerwin.conf 加载kerwin.conf 并启动服务器
​
   nginx -s 
   {
        stop       — fast shutdown 
        reload     — reloading the configuration file(每次修改完kerwin.conf后 ,都通过此方法 重新加载一次)}
静态文件serve
​
location / {
            root   html;//是当前文件夹下有个html文件夹
            index  index.html index.html
        }
​
location /frontend {
            root html ; 
            #只要加载localhost/frontend路径 那么就会从 html/frontend/路径提供文件服务
        }
下面四种情况分别用http://localhost/proxy/test.html 进行访问。
// 注意 /proxy/  后面的/ 需要加上
​
(1)location /proxy/ {
        proxy_pass http://127.0.0.1:8000/; 
    }会被代理到http://127.0.0.1:8000/test.html 这个url

 (2)相对于第一种,最后少一个 /
   location /proxy/ {
        proxy_pass http://127.0.0.1:8000;
   }
   会被代理到http://127.0.0.1:8000/proxy/test.html 这个url
​

 (3)location /proxy/ {
     proxy_pass http://127.0.0.1:8000/xiaoming/;
  }
  会被代理到http://127.0.0.1:8000/xiaoming/test.html 这个url。

  (4)相对于第三种,最后少一个 / :
​
  location /proxy/ {
       proxy_pass http://127.0.0.1:8000/xiaoming;
  }
  会被代理到http://127.0.0.1:8000/xiaomingtest.html 这个url
  • (4)将nginx部署在线上作为webserver serve 静态资源, 并反向代理node服务

Vue3

  • 创建
const app =Vue.createapp('...')
const helloApp={
	data(){
	return{
		message:{
		
			}
		}
	}
}
Vue.createApp('...').mount('#hello-vue')//用mount进行挂载
  • reactive

reactive 是 Vue3 中提供的实现响应式数据的方法。
在 Vue2 中响应式数据是通过 defineProperty 来实现的,
在 Vue3 中响应式数据是通过 ES6 的 Proxy来实现的。
reactive 参数必须是对象 (json / arr)
如果给 reactive 传递了其它对象
默认情况下,修改对象无法实现界面的数据绑定更新。
如果需要更新,需要进行重新赋值。(即不允许直接操作数据,需要放个新的数据来替代原数据)
在 reactive 使用基本类型参数
基本类型(数字、字符串、布尔值)在 reactive 中无法被创建成 proxy 对象,也就无法实现监听。

ref

ref函数接受一个值并返回一个响应式的、可变的Ref对象。Ref对象只有一个.value属性值。

  • 第一种实现,通过reactive方法直接实现
function ref(intialValue){
    return reactive({value:intialValue})
}

  • 对象访问器
    Vue3中ref使用了一个概念对象访问器,这属于JavaScript里计算属性的概念。

toref

toRef用来给抽离响应式对象中的某一个属性,并把该属性包裹成ref对象,使其和原对象产生链接

toRef是做的一种引用关系,修改msg2的值,会影响对象msg,但视图不会发生变化

    setup(){
    	let msg = { name: 'zs', age: 16 }
        let msg2 = toRef(msg, 'name')
        console.log(msg2.value)	// zs
        function change2() {
            msg2.value = 'ww'
            console.log(msg, msg2.value) // {name: "ww", age: 16} ww
            //此时 msg.ww 数据变了 但是视图上的是不会变的
        }
        change2()
        return { msg2,change2 }
    }

3. toRefs的使用

toRefs用来把响应式对象转换成普通对象,把对象中的每一个属性,包裹成ref对象

toRefs就是toRef的升级版,只是toRefs是把响应式对象进行转换,其余的特性和toRef无二

setup(){
    let msg = { name: 'zs', age: 16 }
    let msg3 = toRefs(msg)
    console.log(msg) // { name:ref, age:ref }  ref代指ref对象
    function change3() {
      msg3.name.value = 'zl'
      msg3.age.value = 20
      console.log(msg, msg3) // {name: "zl", age: 20} { name:ref, age:ref }
    }
    change3()
    return { msg3, change3 }
}

  • ref、toRef、toRefs 都可以将某个对象中的属性变成响应式数据
  • ref的本质是拷贝,修改响应式数据,不会影响到原始数据,视图会更新
  • toRef、toRefs的本质是引用,修改响应式数据,会影响到原始数据,视图会更新
  • toRef 一次仅能设置一个数据,接收两个参数,第一个参数是哪个对象,第二个参数是对象的哪个属性
  • toRefs接收一个对象作为参数,它会遍历对象身上的所有属性,然后挨个调用toRef执行

Vue3的生命周期

一、Vue3中的生命周期
1、setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method

2、onBeforeMount() : 组件挂载到节点上之前执行的函数;

3、onMounted() : 组件挂载完成后执行的函数;

4、onBeforeUpdate(): 组件更新之前执行的函数;

5、onUpdated(): 组件更新完成之后执行的函数;

6、onBeforeUnmount(): 组件卸载之前执行的函数;

7、onUnmounted(): 组件卸载完成后执行的函数;

8、onActivated(): 被包含在 <keep-alive> 中的组件,会多出两个生命周期钩子函数,被激活时执行;

9、onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;

10、onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。

vue2           ------->      vue3
 
beforeCreate   -------->      setup(()=>{})
created        -------->      setup(()=>{})
beforeMount    -------->      onBeforeMount(()=>{})
mounted        -------->      onMounted(()=>{})
beforeUpdate   -------->      onBeforeUpdate(()=>{})
updated        -------->      onUpdated(()=>{})
beforeDestroy  -------->      onBeforeUnmount(()=>{})
destroyed      -------->      onUnmounted(()=>{})
activated      -------->      onActivated(()=>{})
deactivated    -------->      onDeactivated(()=>{})
errorCaptured  -------->      onErrorCaptured(()=>{})

watch

  • 监听整个对象
    其第一个参数是直接传入要监听的对象。当监听整个对象时,只要这个对象有任何修改,那么就会触发 watch 方法。无论是其子属性变更(如 demo.name),还是孙属性变更(如 demo.soulmate.name)…,都是会触发 watch 方法的。
watch(demo, (newValue, oldValue) => {
    console.log('watch 已触发', newValue)
})
  • 监听对象中的某个属性

// 监听demo对象的name属性
 
watch(() => demo.name, (newValue, oldValue) => {
    console.log('watch 已触发', newValue)
})

如上代码,监听 demo 对象的 name 属性,那么只有当 demo 对象的 name 属性发生变更时,才会触发 watch 方法,其他属性变更不会触发 watch 方法。

  • 只监听对象的子属性
watch(() => ({ ...demo }), (newValue, oldValue) => {
    console.log('watch 已触发', newValue)
})
  • 监听对象的所有属性
watch(() => demo, (newValue, oldValue) => {
	console.log('watch 已触发', newValue)
}, { deep: true })

这个相当于监听整个对象(效果与上面的第一种相同)。但是实现方式与上面第一种是不一样的,这里我们可以看到,第一个参数是箭头函数,并且还多了第三个参数 { deep: true }。当加上了第三个参数 { deep: true },那么就不仅仅是监听对象的子属性了,它还会监听 孙属性,曾孙属性 …
通常要实现监听对象的所有属性,我们都会采用上面第一种方法,原因无他,第一种编码简单,第一个参数直接传入 demo 即可。

  • 组合监听
watch([() => demo.name, nums], ([newName, newNums], [oldName, oldNums]) => {
	console.log('watch 已触发: name', newName)
	console.log('watch 已触发: nums', newNums)
})

同时监听 demo 对象的 name 属性,和基础类型 nums,只要他们其中任何一个发生变更,那么就触发 watch 方法。

hooks

本质而言,hook就是一个函数,只不过hook是把 setup组合函数之中的 组件api(ref、reactive、conputed、watch、生命周期函数)等进行了封装抽离代码(公共代码,公共组件等),这样使得代码更加简洁
hook 类似于 vue2之中的 mixin

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值