Vue3入门

本文围绕Vue3展开,介绍了其项目创建方式,如用vue-cli和vite创建;阐述了Setup函数、ref和reactive等新特性;讲解了计算属性与监听属性、生命周期;还介绍了toRef与toRefs的作用,以及axios的基础运用和拦截器使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Vue3介绍

关于vue项目的版本,新项目使用vue3,有部分老项目使用vue2。

vue3官方文档

vue3的变化

	1.性能的提升
    -打包大小减少41%
    -初次渲染快55%, 更新渲染快133%
    -内存减少54%
	2.源码的升级
	    使用Proxy代替defineProperty实现响应式
	    重写虚拟DOM的实现和Tree-Shaking
	3.拥抱TypeScript
	    Vue3可以更好的支持TypeScript
	4.新的特性
	    Composition API(组合API)
	    setup配置
	    ref与reactive
	    watch与watchEffect
	    provide与inject
	    新的内置组件
	    Fragment
	    Teleport
	    Suspense
	    其他改变
	
	    新的生命周期钩子
	    data 选项应始终被声明为一个函数
	    移除keyCode支持作为 v-on 的修饰符
	    
	    # vue2配置项与vue3组合式的区别
	        vue2 :配置项API
	             new Vue({
	                 el:'#app',
	                 data:{}
	             })
	
	        vue3: 组合式API
	            let name='kiki'
	            let add=()=>{ 
	            }

二、Vue3项目创建

1)使用vue-cli创建vue3项目

创建跟之前的vue2一样,只是在选择vue版本的时候选择vue3版本,同样用pycharm打开然后配置好配置项后运行即可。

	vue create 名称		// 选择需要的配置 到版本选择3.X即可	
	npm run server		// 运行服务器

在这里插入图片描述

在这里插入图片描述


vue3的项目简单解释

	'main.js'
	import { createApp } from 'vue' # 通过 createApp创建vue实例
	import App from './App.vue'  # 根组件
	import router from './router' # vue-router
	import store from './store' #vuex
	
	var vue = createApp(App) # 创建vue实例
	vue.use(store)#使用vuex
	vue.use(router)# 使用vue-router
	vue.mount('#app')# 挂在index.html中得div
	
	
	'其他地方写起来跟之前写vue2完全一致,vue3是兼容的'

2)使用vite创建vue3项目

Vite 是一个轻量级的、速度极快的构建工具,对 Vue SFC 提供第一优先级支持。作者是尤雨溪,同时也是 Vue 的作者!是新建的前端构架工具,最大的优势就是速度快。

在这里插入图片描述

vite使用步骤

	1. 安装---默认最新版
    	npm create vue@latest  // 这个命令可以根据自己的需求选择功能(如vue-router)
    	npm create vite@latest //这个命令没有选择第三方插件
	2. 在项目中执行npm install 命令 ,虽然vite创建非常快,但是它没有安装依赖,所以需要自己安装一下
		没有这个node_modules依赖
	       
	3  运行npm run dev启动项目

	注意点:
	4. vueRouter跟之前一样
	5. Pinia:用来替换Vuex的,新一代的状态管理器

在这里插入图片描述

在这里插入图片描述


三、Setup函数

简化代码和项目的简洁度,vue新增了setup函数。

  • setup为Vue3.0中一个新的配置项,值为一个函数

  • setup是所有Composition API(组合API)编写的位置

  • 组件中所用到的:数据、方法等等,均要配置在setup中

  • setup函数的返回值:返回一个对象,对象中的属性、方法, 在模板中均可以直接使用

  • 注意:
    尽量不要与Vue2.x配置混用

    • Vue2.x配置(data、methos、computed…)中可以访问到setup中的属性、方法。
      但在setup中不能访问到Vue2.x配置(data、methos、computed…)。
      如果有重名, setup优先。

任意一个页面组件看看效果

	<template>
	  <div class="home">
	    <h1>Setup函数</h1>
	    <hr>
	    <p>名字:{{name}}</p>
	    <p>年龄:{{age}}</p>
	    <button @click="addAge">点击年龄+10</button>
	  </div>
	</template>
	
	<script>
	
	export default {
	  name: 'HomeView',
	  setup(){
	    // setup中没有this了
	    // 以后所有的变量定义函数编写,都写在这个函数中
	    // 定义变量 如果这么写,变量渲染没问题,但是没有响应式,页面变了,变量不会变
	    // vue3中,默认是没有响应式的
	
	    //1.定义变量,跟正常js一样,但是推荐使用let,而不是使用var
	    let name = 'jack'
	    let age = 18
	
	    //2.定义函数
	    let addAge = () => {
	      age+=10
	      console.log(age)  //可以发现变量是变了,但是没有响应式
	    }
	
	    //必须要有返回值,是个对象,返回的对象,可以在模版中使用
	    return {name,age,addAge}
	  }
	}
	</script>

在这里插入图片描述


vue2的创建vue实例和vue3创建vue实例的区别

	'Vue2'
	1.new Vew()--->是Vue的实例,里面有$store,$refs....
	
	'Vue3'
	1.createApp(App)--->是个对象,对象里有东西,没有$store,$refs....等对象,当需要使用直接导入使用
	2.vue3的<template>,不需要写一个标签了
	3.定义变量/函数,都写在setup函数中,都要return函数,在<template>才能使用
	4.但是失去了响应式
	
	总结:
	   1.在setup中定义的变量和函数,在之前配置项api中可以直接使用this.变量,函数调用即可
	   2.但是在原来配置项中定义的变量,函数,在setup中无法使用

四、ref和reactive

	1.导入使用:import {ref, reactive} from 'vue'
	2.基本数据类型(数字,字符串,布尔)如果要加响应式
	      使用ref包裹,在模板中直接读取定义量
	      js中通过对象.value取值
	3.对象,数组引用使用reactive,ref可以包对象类型,但是用的时候必须.value。
	      操作数据与读取数据:均不需要.value

1)ref函数

  • 作用: 定义一个响应式的数据
  • 语法: const xxx = ref(initValue)
    • 创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。
    • JS中操作数据: xxx.value
    • 模板中读取数据: 不需要.value,直接:<div>{{xxx}}</div>
  • 备注:
    • 接收的数据可以是:基本类型、也可以是对象类型。
    • 基本类型的数据:响应式依然是靠Object.defineProperty()get与set完成的
    • 对象类型的数据:内部 求助 了Vue3.0中的一个新函数—— reactive函数
	<template>
	  <div class="home">
	    <h1>Setup函数</h1>
	    <hr>
	    <h3>ref函数</h3>
	    <p>名字:{{name}}</p>
	    <p>年龄:{{age}}</p>
	    <button @click="addAge">点击年龄+10</button>&nbsp;&nbsp;
	    <button @click="handlerChange('吴彦祖')">点击修改名字</button>
	
	  </div>
	</template>
	
	<script>
	import {ref,reactive} from "vue";
	
	export default {
	  name: 'HomeView',
	  setup(){
	    let name = ref('jack')
	    let age = ref(18)  //已经不是数字了,是RefImpl的对象
	
	    //2.定义函数
	    let addAge = () => {
	      age.value+=10
	      console.log(age)	
	    }
	
	    let handlerChange = (data)=>{
	      name.value = data  //属性.value就可以对属性进行操作
	      console.log(name)
	    }

		'''
			如果是拿子组件对象的属性和方法,需要让子组件的属性和方法暴露出来才可以拿到使用
			在子组件中:defineExpose({传入属性、方法}) //这个是可选暴露的,vue2中父组件可以拿到所有
			并且在当前组件中使用子组件的属性或方法,必须定义与子组件中定义的名字相同
		'''
	
	    //必须要有返回值,是个对象,返回的对象,可以在模版中使用
	    return {name,age,addAge,handlerChange}
	  }
	}
	</script>

在这里插入图片描述


2)reactive函数

  • 作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数
  • 语法:const 代理对象= reactive(源对象)接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
  • reactive定义的响应式数据是“深层次的”
  • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作
	<template>
	  <div class="home">
	    <h1>Setup函数</h1>
	    <hr>
	    <h3>reactive函数</h3>
	    <p>用户名:{{userinfo.name}}</p>
	    <p>年龄:{{userinfo.age}}</p>
	    <p>爱好:{{userinfo.hobby[0]}},{{userinfo.hobby[1]}}</p>
	    <button @click="handlerClick">点击年龄+1</button>
	
	  </div>
	</template>
	
	<script>
	import {ref,reactive} from "vue";
	
	export default {
	  name: 'HomeView',
	  setup(){
	
	    let userinfo=reactive({'name':'oscar','age':23,'hobby':['jump','rap']})
	
	
	    let handlerClick = ()=>{
	      userinfo.age++
	      console.log(userinfo)
	    }
	
	    //必须要有返回值,是个对象,返回的对象,可以在模版中使用
	    return {userinfo,handlerClick}
	  }
	}
	</script>

在这里插入图片描述


3)reactive对比ref

	从定义数据角度对比:
		ref用来定义:基本类型数据
		reactive用来定义:对象(或数组)类型数据
		备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象
		
	从原理角度对比:
		ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)。
		reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
		
	从使用角度对比:
		ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
		reactive定义的数据:操作数据与读取数据:均不需要.value。

4)setup的两个注意点

	setup执行的时机
		在beforeCreate之前执行一次,this是undefined。
		
	setup的参数
		props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
		context:上下文对象
			attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs。
			slots: 收到的插槽内容, 相当于 this.$slots。
			emit: 分发自定义事件的函数, 相当于 this.$emit。

五、计算属性与监听属性

1)计算属性(computed函数)

通过绑定ref和rective来编写计算(computed)

	<script>
	import {ref, reactive,computed} from "vue";
	
	export default {
	  name: 'StatsView',
	  setup() {
	    let person = reactive({
	      firstname:'',
	      lastname:'',
	    })
	
	    //计算属性----》获取值 ,单拎出来写
	    // person.fullName = computed(()=>{
	    //   return person.firstname + person.lastname
	    // })
	
	    //计算属性----》修改值  //组合使用
	    person.fullName = computed({
	      get(){  //获取 触发它的执行
	        return person.firstname + person.lastname
	      },
	      set(NewValue){  //修改 触发它,传入修改后的值
	        console.log(NewValue)
	        person.firstname = NewValue.substring(0,1)
	        person.lastname = NewValue.slice(1)
	      }
	    })

	    return {person,}
	  },
	}
	</script>
	
	<template>
	  <div>
	    <h1>计算属性:computed</h1>
	    <hr>
	    <p>姓:<input type="text" v-model="person.firstname"></p>
	    <p>名:<input type="text" v-model="person.lastname"></p>
	    <p>全名:{{person.fullName}}</p>
	    <p>全名修改:<input type="text" v-model="person.fullName"></p>
	  </div>
	</template>

在这里插入图片描述


2)监听属性(watch函数)

	<script>
	import {ref, reactive,computed,watch} from "vue";
	
	export default {
	  name: 'StatsView',
	  setup() {
	    let count = ref(0)
	
	    let AddCount = ()=>{
	      count.value++
	    }
	
	    //监听基本类型
	    watch(count,(NewValue,OldValue)=>{
	      console.log(OldValue,NewValue)
	    })
	
	    //监听对象
	    let userinfo = reactive({
	        name:'jack',
	        age:22
	    })
	    let handlerName=()=>{
	      userinfo.name = '彭于晏'
	    }
	    watch(()=>userinfo.name,(NewValue,OldValue)=>{
	      console.log('名字变更了:'+userinfo.name)
	    })
	
	    //可以同时监听多个变量
	    /*
	     const sum = ref(100)
	     const msg = ref('很好')
	     watch([sum, msg], (newValue, oldValue) => {
	      console.log('sum或msg变化了', newValue, oldValue)
	    }) 
	    */
	
	    return {person,count,AddCount,userinfo,handlerName}
	  },
	}
	</script>
	
	<template>
	  <div>
	    <h1>监听属性:watch---基本类型</h1>
	    <p>数量:{{count}}</p>
	    <button @click="AddCount">点击数量+1</button>
	    <hr>
	    <h1>监听属性:watch---对象</h1>
	    <p>名字:{{userinfo.name}}</p>
	    <button @click="handlerName">点击变换名字</button>
	
	    <hr>
	  </div>
	</template>

在这里插入图片描述
补充watchEffect函数

  • watch的套路是:既要指明监视的属性,也要指明监视的回调。
  • watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
  • watchEffect有点像computed:
    • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
    • 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
	//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
	watchEffect(() => {
	      const x1 = sum.value
	      const x2 = person.age
	      console.log('watchEffect配置的回调执行了')
	    })

六、Vue3生命周期

  • Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
    • beforeDestroy改名为 beforeUnmount
    • destroyed改名为 unmounted
  • Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
    • beforeCreate===>setup()
    • created=======>setup()
    • beforeMount ===>onBeforeMount
    • mounted=======>onMounted
    • beforeUpdate===>onBeforeUpdate
    • updated =======>onUpdated
    • beforeUnmount ==>onBeforeUnmount
    • unmounted =====>onUnmounted

注意:vue3中的配置项方式的生命周期还是跟vue2的一样,上面的是vue3的组合式方式的

使用

'在想要使用的组件中导入想使用的某些或某个即可'
import {onBeforeMount, onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from "vue";
'注意,在vue3中beforecreate和created都被setup替代,因为setup里面就是直接写变量,没写的时候就相当于没赋值'

'例子'
setup(){
    onMounted(()=>{
       console.log('挂载完毕')
     })

     onUpdated(()=>{
       console.log('更新完毕')
     })
}

'例如想在组件加载完成前就设置一个定时器'
setup(){
    '直接在setup中写就行了,vue2中还需要写this,在setup中无需写了直接用'
	let t = null
    setInterval(()=>{},3000)
    onBeforeUnmount(()=>{
      clearInterval(t)
      t=null
    })
}

在这里插入图片描述


七、toRef与toRefs

  • toRef的作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性。
  • 语法:const name =toRef(person,'name')
  • 应用: 要将响应式对象中的某个属性单独提供给外部使用时。
  • 扩展:toRefstoRef功能一致,但可以批量创建多个ref 对象,语法:toRefs(person)

补充es解构赋值

	//解构赋值
	let person = {name:'jack',age:18}
	// let {name,age} = person  //普通解构赋值  相当于name=person.name
	// console.log(name,age)
	let {name:a,age:b} = person  //重命名解构赋值 a=person.name
	console.log(a,b)
	<script>
	import {ref,reactive,toRef,toRefs} from "vue";
	
	export default {
	  name:'TorefView.',
	  setup(){
	    let data = reactive({
	      name:'jack',
	      age:22,
	      hobby:'rap'
	    })
		
		console.log({...toRefs(data)}) //解压赋值
		
	    let count = ref(11)

    	return {...toRefs(data),count} //解压赋值,后续写影响
	  }
	}
	</script>
	
	<template>
	  <h1>toRef函数</h1>
	  <hr>
	  <p>名字:{{name}}</p>
	  <p>年龄:{{age}}</p>
	  <p>爱好:{{hobby}}</p>
	</template>

在这里插入图片描述

	<script setup lang="js">
	import {ref,reactive,toRef,toRefs} from "vue";
	import axios from 'axios'
	
	//toRefs
	const person = reactive({name:'jack',age:18})  //设置响应式
	// let res = toRefs(person)  //把里面所有的普通变量变成响应式  name=ref('jack')
	// let res1 = person  //单纯的解构
	// console.log(res)
	// console.log(res1)
	let {name,age} = toRefs(person) //这样就相当于解构赋值变成响应式的  name=ref('jack')
	console.log(name)
	function addAge(){
	  age.value++
	  console.log(age.value)
	}
	
	function addName(){
	  name.value = 'oscar'
	  console.log(name.value)
	}
	
	</script>
	
	<template>
	  <h1>toRefs</h1>
	  <p>名字:{{name}}</p>
	  <p>年龄:{{age}}</p>
	  <button @click="addAge">点击年龄+1</button>
	  <button @click="addName">修改名字</button>
	</template>

在这里插入图片描述


八、axios

axios基础运用

1.安装

	npm install axios -S

2在组件中使用.

	导入:import axios from 'axios'
	然后直接在setup中直接使用

小案例

	<script setup lang="js">
	import {ref,reactive} from "vue";
	import axios from 'axios'
	
	1.方式一:
	// 加载电影数据  //设置响应式
	let filmList = reactive({result:[]})
	//发送ajax
	axios.get('http://localhost:8000/api/v1/movies/').then(res=>{
	  console.log(res.data.data.films)
	  //因为响应式影响filmList,如果直接赋值,这样响应式就没有了,
	  // filmList = res.data.data.films  //这样响应式就没有
	  //所以在里面设置一个对象,让它来接收,这样响应式就还在,深层次响应式
	  filmList.result = res.data.data.films
	})

	2.方式二:
	//使用asyncawait定义,async异步
	//异步请求
	const filmList = reactive({result:[]})
	async function load(){
	  //await必须写在被async修饰的函数中
	  let response = await axios.get('http://localhost:8000/api/v1/movies/')
	  filmList.result=response.data.data.films
	}
	</script>
	
	<template>
	  <div v-for="film in filmList.result">名字:{{film.name}}</div>
	</template>

在这里插入图片描述


axios拦截器

1.什么是axios拦截器、为什么要使用axios拦截器?

在vue项目中,我们通常使用axios与后台进行数据交互,axios是一款基于promise封装的库,可以运行在浏览器端和node环境中。

2.axios特性

  • 1、拦截请求和响应
  • 2、取消请求
  • 3、转换json
  • 4、客户端防御XSRF等。

3.使用拦截器的原因

若出现请求数多的情况下,我们将会用到 axios 的一个API:拦截器。
页面发送http请求,很多情况我们要对请求和其响应进行特定的处理,
如果每个请求都附带后端返回的token,我们需要在拿到response之前loading动画的展示等。

4.拦截器的分类

拦截器分为 请求(request)拦截器响应(response)拦截器

5.拦截器的使用

在请求或响应被 then 或 catch 处理前拦截它们。

1.请求拦截器

	// 添加请求拦截器
	axios.interceptors.request.use(
	    function (config) {
	        do......
	        // 在发送请求之前进行操作
	        return config;
	    },
	    function (error) {
	        do......
	        // 对请求错误进行操作
	        return Promise.reject(error);
	    }
	);

举例:

	// http request 拦截器
	axios.interceptors.request.use(
	    config => {
	        if (store.state.token) { 
	         // 判断是否存在 token, 如果存在的话, 则每个 http header 都加上 token
	            config.headers.Authorization = `token ${store.state.token}`;
	        }
	        return config;
	    },
	    err => {
	        return Promise.reject(err);
	    });

2.响应拦截器

	// 添加响应拦截器
axios.interceptors.response.use(
    function (response) {
        // 对响应数据进行操作
        return response;
    },
    function (error) {
        // 对响应错误进行操作
        return Promise.reject(error);
    }
);

举例:

	// http response 拦截器
	axios.interceptors.response.use(
	    response => {
	        return response;
	    },
	    error => {
	        if (error.response) {
	            switch (error.response.status) {
	                case 401:
	                    // 返回 401 清除 token 信息并跳转到登录页面
	                    store.commit(types.LOGOUT);
	                    router.replace({
	                        path: 'login',
	                        query: {redirect: router.currentRoute.fullPath}
	                    })
	            }
	        }
	        return Promise.reject(error.response.data)  
	         // 返回接口返回的错误信息
	    });

说明:

如果我们使用中需要统一处理所有 http 请求和响应, 就需要使用 axios 拦截器。
通过配置 http response inteceptor, 如果后端接口返回 401 Unauthorized(说明该用户未授权), 用户需重新登录。

3.移除拦截器:

	const myInterceptor = axios.interceptors.request.use(function () {
	 do ...... 
	//具体的操作
	});
	axios.interceptors.request.eject(myInterceptor);
	
	
	为自定义 axios 实例添加拦截器:
	
	const instance = axios.create();
	instance.interceptors.request.use(function () { 
	    do ...... 
	   //具体的操作
	});

九、补充

	1.在vue3中使用子组件方式
		-在vue3配置项方式中导入后需要配置components才可以在模版中使用,和vue2写法一样
			<script>
				import HelloWorld from "@/components/HelloWorld.vue";
				export default {
					components: {HelloWorld},
					setup(){
						
					}
				}
			</script>
			
			<template>
			  <HelloWorld msg="hello world"></HelloWorld>
			</template>
			
		-在vue3组合式方式中导入后,直接可以在模版中使用了,但是需要导入到后缀.vue才行
			<script setup>
				import HelloWorld from "@/components/HelloWorld.vue";
			</script>
			
			<template>
			  <HelloWorld msg="hello world"></HelloWorld>
			</template>
	
	2.vue3中路由跳转方式:
		-在vue3配置项方式中导入后然后定义对象才行,然后配置事件return出去即可
			<script>
				import {useRoute,useRouter} from "vue-router";
				export default {
				  setup(){
				      const router = useRouter()  //就是以前this.$router
				      const route = useRoute()	  //就是以前this.$route
				
				      function Tiao(){
				        router.push('/')
				      }
				      return {Tiao}
				  },
				}
			</script>
			
		-在vue3组合式方式中和配置项几乎一样,仅仅只是配置事件后无需return而已
		-携带数据跳转也是一样的操作
			
			
	3.路由嵌套、路由守卫也是和vue2一样

	4.vue3上的状态管理器更推荐使用pinia,当然也可以使用vuex
		-在vue3上使用vuex的话和vue2差不多
		-在vue3上使用pinia,在组件中导入和定义一个store对象
			import {useCounterStore} from '@/stores/counter'
			//可以在组件中的任意位置访问 `store` 变量 ✨
			const store = useCounterStore()
			//console.log(store.count)
			// let handleAdd = () => {
			//   store.count++
			// }
	
	5.vue3上使用element-plus,不是element-ui了,具体使用看官方文档即可

	最后vue3小细节
	//在script标签中写了setup 以后这里面的东西就相当于写在setup中了
	//lang=js意味着在setup中只写js,如果是lang=ts意味着在setup中只写typescript
	//原来的setup中必须要返回出来,现在无需返回了,可以直接在template中直接使用了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值