$vue3介绍及使用$

【一】vue3介绍

【0】补充

# 在 Vue 3 中,"API" 指的是用于开发的编程接口。选择式 API 和组合式 API 是两种编写 Vue 组件的方式:

# 选择式 API(Options API):这是 Vue 2 中的传统方式,通过配置对象(如 data、methods、computed)来定义组件的行为和状态。

# 组合式 API(Composition API):这是 Vue 3 引入的新方式,通过函数(如 ref、reactive、computed、watch)来组织和复用组件逻辑,使代码更加灵活和可维护。

# 两者的核心区别在于组织组件逻辑的方式和代码的结构。

# vue-cli 是一个官方提供的脚手架工具,可以快速生成 Vue 项目的模板和配置。通过运行 vue create my-project 命令,可以创建一个新的 Vue 2 项目(在选择 Vue 版本时选择 Vue 2)

# 创建和管理 Vue 项目通常需要 Node.js。Node.js 提供了 JavaScript 运行时环境和包管理工具(如 npm 或 yarn),这些工具是生成、安装依赖和运行开发服务器所必需的

【1】前言

# vue3 完全兼容vue2的所有东西
# vue3不建议使用vue2的写法,配置项API

# vue3 有两种方式
	- 选择式API:就是vue2的写的法
    	export default {
            data() {
                return {
                    username: "",
                    password: ""
                	}
            	}
        	}
    - 组合式API// 定义变量和函数在一起定义
    	const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
        // 也可以直接写函数
        function add(){ 
        }

【2】快速体验组合式使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style></style>
</head>
<body>
<div id="app">

    <p>{{count}}</p>
    <br>
    <button @click="handleAdd">点我加1</button>


</div>
</body>
<script>

    let app=Vue.createApp({
        setup() {
            let count=Vue.ref(0)
            let handleAdd=()=>{
                count.value++
            }
            return {
                count,
                handleAdd
            }
        },

    })
    app.mount("#app")

</script>
</html>

【3】快速体验配置项

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style></style>
</head>
<body>
<div id="app">

    <p>{{count}}</p>
    <br>
    <button @click="handleAdd">点我加1</button>


</div>
</body>
<script>

    let app=Vue.createApp({
        data(){
            return {
                count:100
            }
        },
        methods:{
            handleAdd(){
                this.count++
            }
        }
    })
    app.mount("#app")

</script>
</html>

【4】拥抱ts (TypeScript)

# 我们之前写vue2用js
# vue3--》可以使用ts-->微软推出的--》最终要被编译成js才能运行在浏览器中
# 使用ts写,可以避免很大错误---》ts对类型有强制要求
# ts是js的超集---》ts完全兼容js
# 我们学的是
	vue2+js+vue-router+vuex+elementui
	vue3+js+vue-router+pinia+elementui-plus
# 

【二】创建Vue3的项目

【1】使用vue-cli创建

# 创建vue2项目是我们在cmd中创建的,vue3也可以

# 另一种创建vue项目的方法,cmd打开终端,输入:vue ui--->就会打开一个图形化界面
	- 你执行命令的时候要切换到你创建vue项目的路径,在执行vue ui
    - 打开后,创建项目,书写项目名,包管理:npm
    - 下一步,手动,
    - 下一步:选择你使用的插件
    - 下一步:选择vue版本,选择路由模式
# 在vue3中导入的文件必须带后缀.vue

【2】使用vite创建(vue3推荐使用这个)

# 使用vite创建vue3的项目,新一代前端构建工具
	- 进入官网:https://vitejs.cn/
   	- 根据下载步骤在终端中安装
    - 优势如下:
    开发环境中,无需打包操作,可快速的冷启动。
    轻量快速的热重载(HMR)。
    真正的按需编译,不再等待整个应用编译完成。

# 2 兼容性注意---》nodejs的版本兼容问题
Vite 需要 Node.js 版本 18+20+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本

# 3 创建vue3工程

# 配置npm镜像站:npm config set registry https://registry.npmmirror.com
	- 镜像源来提高下载速度或保证资源的可用性
# 查看镜像站:npm config get registry

# 不指定名字创建:npm create vite@latest
# 指定名字创建 
    # 创建项目方式一
    	npm create vite@latest
        - 创建的时候要输入项目名字
	# 创建项目方式二:指定名字
    	npm create vite@latest vue3_demo002
    # 创建项目方式三
    	cnpm create vite@latest vue3_demo002
    # 创建项目方式四
    	cnpm create vite vue3_demo002
# 3 使用编辑器打开vue3项目
# 4 安装依赖
	npm install 
# 5 运行项目
	npm run dev
    
# 你的终端路径在哪,项目就会创建到哪

【3】补充

####我们运行项目的时候vite创建的项目需要 npm run dev
# vue-cl创建的项目需要:npm run serve

### 我们可以修改
##在package.json文件中,
{
  "name": "vue3_one",
  "version": "0.1.0",
  "private": true,
  "scripts": {
      # 改这个名字,就可以修改,启动的名字
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build"
  },

【三】常用API

【1】定义变量统一用const

# 1 const是常量--》不允许变的
# 2 咱们用 ref包裹后,是个对象,虽然对象是常量,对象不能变,对象.value可以变化
# 3 之所以定义成const原因是,后期不能修改对象 【对象.value可以改】
# 4 如果用let声明 ,后期修改对象不会报错,导致程序出问题

【2】组合式和选择式混用—不推荐

# 组合式和选择式可不可以混用
	- 可以
    - 但是我们用一种就可以了
    - 并且在选择式api的方法中,可以拿到setup函数中定义的变量

【3】setup函数

  • 前言
# 这里vue3项目如果使用选项式API创建的,写法和vue2一模一样

# 但是你要是用组合式创建的vue3的项目,所有的script里面的代码都要写在setup中

# srtup函数必须return返回变量和函数--》你才可以在template中使用

# 默认不带响应式,需要使用ref或reactive包裹
	- 比如:const name = ref('lqz')
    - 比如:const info = reactive({name: 'lqz', age: 19})
  • 使用
#########我们直接定义变量是不会有响应式的,意思就是你的值虽然变了但是你的页面没变
<template>
  <div class="about">
    <h1>vue3的组合式写法</h1>
    <h1>{{count}}</h1>
    <button @click="add">点击加1</button>
  </div>
</template>

<script>
export default {
  name:'AboutView',
  setup () {
      // 定义变量
    let count=100
    function add(){
      count++
        // 这里打印的count已经是加1的状态,但是页面上没有响应
        // 所以我们需要,ref这个类进行包裹count,才会有响应式
      console.log(count)
    }
    return {count, add}
  }
}
</script>

【4】ref类

  • 前言
# 使用ref包裹的数据[数字,字符串,布尔],使其具有响应式的类
# 不使用ref包裹就不具有响应式

# 所以在vue3中响应式可以由我们自己判断

# 使用ref需要导入
import {ref} from "vue";
  • 使用
<template>
  <div class="about">
    <h1>vue3的组合式写法</h1>
    <h1>{{count}}</h1>
    <button @click="add">点击加1</button>
  </div>
</template>

<script>
import {ref} from "vue";
export default {
  name:'AboutView',
  setup () {
      // 定义常量
    const count=ref(100)
    function add(){
      // 打印出来的是一个对象,而不是一个数据,count是ref的对象
      console.log(typeof count)// object
      // 这里就不可以直接加1了,取值加1
      count.value++
    }
    return {count, add}
  }
}
</script>

【5】reactive类

  • 前言
# 使用reactive包裹的数据[数字,字符串,布尔],使其具有响应式的类
# 使用需要导入
import {reactive} from "vue";
  • 使用
<template>
  <div class="about">
        <h1>vue3的组合式写法之reactive</h1>
<!--       因为是对象-->
        <h1>名字:{{dict_name.name}}</h1>
        <h1>年龄:{{dict_name.age}}</h1>
    <button @click="add_age">点击年龄加1</button>
  </div>
</template>

<script>
import {reactive} from "vue";
export default {
  name:'AboutView',
  setup () {
    // reactive包裹
      // 对象
    // const dict_name=reactive({name:'lsk',age:18})
    // const add_age = ()=>{
     //  dict_name.age++
    // }
       // 数组
        const dict_name=reactive(['lsk',18])
    	const add_age = ()=>{
      	dict_name[1]++
    	}
    return {count, add, dict_name, add_age}
  }
}
</script>

【6】计算属性

  • 前言
# 需要导入
import {computed} from "vue";
  • 使用
<template>
  <div class="about">
    <!--        <h1>vue3的组合式写法之计算属性</h1>-->
    <p>名字:<input type="text" v-model="input_data.input_name"></p>
    <p>地址:<input type="text" v-model="input_data.attr"></p>
    <p>名字地址:<input type="text" v-model="input_data.name_attr"></p>
  </div>
</template>

<script>
import {computed} from "vue";

export default {
  name: 'AboutView',
  setup() {
    // 计算属性
    const input_data = reactive({input_name: '', attr: ''})
    
    // 如果只用计算属性的话,就不需要有get和set,直接用就可以
    // input_data.name_attr = computed(()=>{return input_data.input_name + input_data.attr} )
    //相当于添加到reactive类中了 input_data.name_attr
    input_data.name_attr = computed({
        // 格式
          get() {
            // 修改input_name和addr会触发这里
            return input_data.input_name + input_data.attr
          }, 
        // 格式
        set(value) {
            // 修改name_attr会触发这里,这里传了一个value:被修改的值
            //slice切分
            input_data.input_name = value.slice(0, 1)
            input_data.attr = value.slice(1)
          }
        }
    )
    return {input_data}
  }
}
</script>

【7】监听属性

(1)监听值类型,监听对象类型,监听多个变量

  • 前言
# 需要导入
import {watch} from "vue";
  • 使用
<template>
  <div class="about">
    <!--        <h1>vue3的组合式写法之监听属性值类型</h1>-->
    <h1>{{ height }}</h1>
    <button @click="handleHeight">身高+1</button>
    <!--        <h1>vue3的组合式写法之监听属性对象类型</h1>-->
    <h1>{{ data_dict.name }}</h1>
    <button @click="change">名字</button>
    <!--        <h1>vue3的组合式写法之监听属性监听多个</h1>-->
    <h1>{{sum}}</h1>
    <h1>{{msg}}</h1>
    <button @click="changeValue">点击</button>
  </div>
</template>

<script>
import {watch} from "vue";

export default {
  name: 'AboutView',
  setup() {
    // 监听属性:监听值类型
    const height = ref(180)

    function handleHeight() {
      height.value++
    }

    watch(height, (newValue, oldVale) => {
      console.log("height发生了变化", newValue, oldVale)
    })
    // 监听属性:监听对象类型
    const data_dict = reactive({name: 'lsk'})

    function change() {
      data_dict.name = '彭昱畅'
    }

    watch(() => data_dict.name, (newVale, oldValue) => {
      console.log("name发生了变化", newVale, oldValue)
    })
    //  监听属性:监听多个类型
    const sum = ref(100)
    const msg = ref('很好')
    function changeValue(){
      sum.value++
      msg.value='很不好'
    }
    // 这两个不管是哪个都会一起执行
    watch([sum,msg],(newValue,oldVale)=>{
      console.log("sum或msg发生了变化")
    })
    return {height, handleHeight, data_dict, change,sum,msg,changeValue}
  }
}
</script>

(2) watchEffect函数

  • 前言
# 使用需要引入
import {watchEffect} from "vue";
  • 使用
# watchEffect 使用:不用指定监听谁,只要watchEffect内部用了某个变量,某个变量发送变化,就会触发
# 如果两个同时都变化,只会执行一次
watchEffect(() => {
    const x1 = sum.value
    const x2 = person.name
    console.log('watchEffect配置的回调执行了')
})

【8】注册小组件

<template>
  <div class="home">
  <h1>vue3的生命周期钩子</h1>
<HelloWorld></HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "@/components/HelloWorld.vue";
export default {
  name: 'HomeView',
    // 注册子组件
  components: {HelloWorld},
  setup(){

  }
}
</script>

【四】生命周期

# vue2中8个生命周期钩子
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed

# vue3中8个生命周期钩子---》选择式API----后两个周期钩子改了
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeUnmount
unmounted

# vue3 组合式api的生命周期钩子
# 直接在setup中使用
beforeCreate===>setup()
created=======>setup()
# 需要引入
import {onBeforeMount,onMounted,...} from "vue";
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted

【1】vue3的选择式api生命周期钩子

export default {
  name: 'HomeView',
    //创建前
  beforeCreate() {
    console.log('beforeCreate')
  },
    // 创建好
  created() {
  },
    // 即将挂载
    // 会在组件的 DOM 元素被挂载到页面之前被调用
    // 意思就是:DOM元素即将被渲染到页面上,之前会执行这里
  beforeMount() {
    console.log('beforeMount')
  },
  mounted() {
  },
  beforeUpdate() {
  },
  updated() {
  },
  beforeUnmount() {
  },
  // 被销毁时执行清理操作
  unmounted() {
    console.log('unmounted')
  }

}

【2】vue3的组合式生命周期钩子

<template>
  <div class="home">
    <h1>生命周期</h1>
    {{ name }}
    <br>
    <button @click="handleClick">点我变名字</button>
  </div>

</template>

<script>

import {
  ref,
  reactive,
  watch,
  computed,
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted
} from 'vue'
import axios from 'axios'

export default {
  name: 'HomeView',
  setup() {
    //1 这里写的代码,就是 beforeCreate,没有数据[变量没定义],没挂载
    console.log('beforeCreate')
    // 2 这里写代码,就是created,有数据,变量定义了,没挂载
    let name = ref('lqz')
    axios.get('http://127.0.0.1:8000/film/').then(res => {
      name.value = res.data.msg
    })
    // 3 onMounted
    onMounted(() => {
      console.log('挂载完了')
    })
    // 4 onUpdated
    onUpdated(() => {
      console.log('页面更新')
    })
    // 5 onUnmounted
    onUnmounted(() => {
      console.log('组件销毁')
    })
    let handleClick = () => {
      name.value = 'afdasdfasdfasdf'
    }

    return {name, handleClick}
  },
}
</script>

在这里插入图片描述

【五】setup的特殊写法

  • 前言
# 在vue3之前组件的写法是这样的
export default {
  name: 'HomeView',
  setup() {
  }
}
  • 使用(重点)

【1】组件导入问题

# 1. 组件只需要导入,就可以自动注册,必须带后缀vue

【2】setup写法

# 2. setup的写法
# lang='js':加上这个代之只允许写js的代码,不写默认也是js,也可以写ts,ts完全兼容js
<script setup lang='js'>
    // 在这里直接写原来的setup代码就行,也不需要return</script>

【3】生命周期钩子

# 3 生命周期钩子--没有这种beforeCreate,created,只有这种了on。。。。

【4】监听属性和计算属性

# 监听属性
    和之前一样
    # 需要导入
    import {watch} from "vue";
# 计算属性
	和之前一样
	# 需要导入
    import {computed} from "vue";

【5】组件间通信:父传子

# 5 组件间通信 父传子
	# 父组件中:跟之前一样
      <HelloWorld :msg="msg"></HelloWorld>
    # 子组件中,接收:
    defineProps({
      msg: String,
    })

【6】组件间通信:子传父

# 6 组件通信,子传父
	-父组件中:
    	# template
          <HelloWorld @send="handleReceive"></HelloWorld>
          <p>父组件中得name:{{name}}</p>
	    # js
        <script setup>
            const name = ref('')
            function handleReceive(a){
              name.value=a
            }
          </script>
    -子组件中:
    	# js
            let $emit = defineEmits(['send']) # 等同于之前的  this.$emit
            const name =ref('')
            const handleSend=()=>{
              $emit('send',name.value)
            }
		# template
         <input type="text" v-model="name">-->{{name}}
          <br>
          <button @click="handleSend">点我传给父亲</button>

【7】ref使用

(1)普通的标签上使用

<script setup>
import {ref} from 'vue'
import HelloWorld from '../components/HelloWorld.vue'
const sonHelloWorld = ref('')
const imgRef = ref('')
const handleClick = ()=>{
  // 得到img对象
  console.log(imgRef.value)
  // 得到图片的高
  console.log(imgRef.value.height)
}
</script>

<template>
  <img src="https://img0.baidu.com/it/u=3500946991,363774577&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1422" alt=""
       height="400px" width="230px" ref="imgRef">
  <button @click="handleClick">ref的信息</button>
</template>

<style scoped>

</style>

(2)组件上使用

###介绍一下defineExpose
# 作用:用于控制组件内部的状态和方法的暴露,可以让函数中声明的变量和方法可以在父组件中访问
# 暴露组件实例的属性、增强组件的可控性
# 你希望父组件能够访问子组件中定义的变量,你就要将变量定义在defineExpose中,不定义就不可以使用
########父组件
<script setup>
import {ref} from 'vue'
import HelloWorld from '../components/HelloWorld.vue'
const sonHelloWorld = ref('')
const imgRef = ref('')
const handleClick = ()=>{
  // 得到组件对象
  console.log(sonHelloWorld.value)
  // 得到组件的one数据,但是,你要在组件中生命这个变量
  console.log(sonHelloWorld.value.one)
}
</script>

<template>
  <HelloWorld ref="sonHelloWorld"></HelloWorld>
  <button @click="handleClick">ref的信息</button>
</template>


#############子组件
<script setup>
import {ref} from 'vue'
const one = ref('lsk')
// 这个声明了常量可以被父组件中使用
defineExpose({one})
</script>

<template>
  <h1>{{ one }}</h1>
</template>

【8】插槽使用

####子组中####
### vue3中的指定插槽,有锁不同
###我们要看将你需要指定显示在子标签中的标签包裹在template标签中并用v-slot:变量名,指定名字,即可使用
  • 子组件
<script setup>
import {ref} from 'vue'
const one=ref('lsk')
</script>
<template>
  <slot name="img1"></slot>
  <h1>{{ one }}</h1>
  <slot name="img2"></slot>
</template>
  • 父组件
<script setup>
import HelloWorld from "../components/HelloWorld.vue";
</script>

<template>
<!--子组件-->
  <HelloWorld ref="sonHelloWorld">
      <!--定义名字,img1-->
    <template v-slot:img1>
      <img src="https://img0.baidu.com/it/u=3500946991,363774577&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1422" alt=""
           height="400px" width="230px" ref="imgRef">
    </template>
      <!--定义名字,img2-->
    <template v-slot:img2>
      <img src="https://img2.baidu.com/it/u=257129803,3739575362&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500" alt=""
           height="400px" width="230px" ref="imgRef">
    </template>
  </HelloWorld>
</template>

【六】toRefs

  • 前言
# 用于将响应式对象中的每个属性转换为单独的响应式引用(ref)。它通常用于将一个响应式对象中的属性解构到单独的 ref 中,这样可以更方便地在模板或其他组件中使用这些属性。

# 用法:toRefs 接受一个响应式对象,并返回一个对象,其中包含原对象的每个属性,每个属性都是一个 ref。这样可以保持这些属性的响应性。

# toRef:给某个属性赋予响应式
	- let name=toRef(对象,'name')
  • 使用
<script setup>
import {reactive, toRefs, toRef} from 'vue'

const dict_data = reactive({name: "lsk", age: 22})
// 解构赋值:直接结构出来的属性是没有响应式的
// let {name, age} = dict_data
// age = 19
// console.log(name)
// console.log(typeof name)  //是一个值类型
// console.log(dict_data.age)  //原来的属性值是不会被改变的,不具有响应式

// toRefs的使用,进行结构赋值,给每个值赋予响应式
// 解构出来的name就是:const name=ref('lsk')
// let {name, age} = toRefs(dict_data)
// console.log(name)  //是ObjectRefImp对象
// console.log(typeof name)  // 得到的是对象类型
// age.value=99
// console.log(dict_data.age)  //具有响应式,值被改变

// toRef的使用,只对单独的一个值赋予响应式
let age=toRef(dict_data,'age')
console.log(age.value)
</script>

【七】axios使用

  • 前言
## 安装:cnpm install axios -S

##还有一个方法
# 这个方法是:将res.data.result对象的属性复制到film_list.film_data上
Object.assign(film_list.film_data, res.data.result)
  • 使用
<script setup>
import {reactive} from "vue";
import axios from "axios";

const film_list = reactive({film_data: []})
const handleFilm = () => {
  axios.get('http://localhost:8000/api/v1/films/film/').then(res => {
    // 正常赋值
    // film_list.film_data= res.data.result
    // 还有一个方法:将res.data.result对象的属性复制到film_list.film_data上
    // Object.assign(film_list.film_data, res.data.result)
    // console.log(film_list.film_data)

    // 结构赋值
    // let {code, msg, result} = res.data
    // console.log(code)
    // console.log(msg)
    // console.log(result)
    // let {result}=res.data
    // console.log(result) //也是可以拿到的
    // Object.assign(film_list.film_data,result)
    // let {data:{result}}=res
    // console.log(result)
    // 这个方法,必须是名字相互对应
    let {data}=res
    Object.assign(film_list,data)
    console.log(film_list.film_data)//film_data必须和data中的我们要的数据名字一样,不然取不到
  })
}
</script>

<template>
  <h1>toRefs的使用</h1>
  <button @click="handleFilm">像后端发送信息</button>
</template>

<style scoped>

</style>
  • async+await写法
<script setup>
import {reactive} from "vue";
import axios from "axios";

const film_list = reactive({film_data: []})
// 相当于定义了一个协程函数---函数的内部有io操作就写await,原来then的值直接赋值给一个表变量
// 如果里面要写await函数必须是async
async function load(){
  // await:代表的是io操作,
  // let {data} = await axios.get('http://localhost:8000/api/v1/films/film/')
  // 协程函数就是,这个请求不回来,不会等待,继续往下执行
  // 如果不是协程函数,就会一直等待
  let res = await axios.get('http://localhost:8000/api/v1/films/film/')
  // 赋值
  Object.assign(film_list.film_data,res.data.result)
  console.log(film_list.film_data)
}

// 执行这个函数
// load()
// 也可以这样执行
const handleFilm = ()=>{
  load()
}
</script>

【八】promise语法

【1】普通函数

###普通函数: 正常调用的函数,一般函数执行完毕后才会继续执行下一行代码
<script setup>
// 挨个执行
let function1=()=>{
  console.log('执行了1')
}
function1()
console.log('继续执行')

</script>

【2】回调函数

#######回调函数: 一些特殊的函数,表示未来才会执行的一些功能,后续代码不会等待该函数执行完毕就开始执行了
<script setup>
let function1=()=>{
  console.log('执行了1')
}
function1()
// 不会阻塞,到时间才会执行这个,不会按顺序执行
setTimeout(()=>{
  console.log("1秒后执行了")
},1000)
console.log('继续执行')
</script>

【3】promise介绍

#### 前端中的异步技术:多线程+线程结果回调---用的就是promise

# Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。

# 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

# Promise对象有以下两个特点。1)Promise对象代表一个异步操作,有三种状态:`Pending`(进行中)、`Resolved`(已完成,又称 Fulfilled)和`Rejected`(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是`Promise`这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从`Pending`变为`Resolved`和从`Pending`变为`Rejected`。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。

# 生活中案例
你跟你女朋友说,5年后等我赚够500w就结婚--》定义函数

    ​ -1 进行中(努力赚钱,其他代码继续执行)
    ​ -2 成功(赚够500w---》结婚)
    ​ -3 失败(没赚够---》分手)

【4】promise基本使用

// ES6规定,Promise对象是一个构造函数,用来生成Promise实例
<script setup>
       /*  
        1.实例化promise对象,并且执行(类似Java创建线程对象,并且start)
        参数: resolve,reject随意命名,但是一般这么叫!
        参数: resolve,reject分别处理成功和失败的两个函数! 成功resolve(结果)  失败reject(结果)
        参数: 在function中调用这里两个方法,那么promise会处于两个不同的状态
        状态: promise有三个状态
                pending   正在运行
                resolved  内部调用了resolve方法
                rejected  内部调用了reject方法
        参数: 在第二步回调函数中就可以获取对应的结果 
        */
let promise = new Promise(function (resolve, reject) {
  console.log('开始执行')
  // 这两个不可以同同时执行
  resolve('promise,执行成功')
  // reject('promise,执行失败')
})
console.log(111)
    // 获取回调函数结果,then会等待promise中的运行结果,但不会阻塞代码的运行
promise.then(
    function (value) {console.log(`执行成功:${value}`)},
    function (error) {console.log(`执行失败:${error}`)}
)
console.log(222)

执行的顺序
// 开始执行
// 111
// H222
// 执行成功:promise,执行成功
</script>

【5】catch情况(异常情况)

<script setup>

let promise = new Promise(function (resolve, reject) {
  console.log('开始执行')
  // 这两个不可以同同时执行
  //  执行成功,走then
  // resolve('promise,执行成功')
  // 执行失败,走catch
  // reject('promise,执行失败')
  // 故意响应一个异常对象,走catch
  throw new Error('走catch')
})
console.log(111)
// 正确的代码会走then,异常的代码会走catch包括reject
/* 
        then中的reject()的对应方法可以在产生异常时执行,接收到的就是异常中的提示信息
        then中可以只留一个resolve()的对应方法,reject()方法可以用后续的catch替换
        then中的reject对应的回调函数被后续的catch替换后,catch中接收的数据是一个异常对象
        */
promise.then(
    function (value) {console.log(`执行成功:${value}`)}
).catch(
    function (error) {console.log(`执行失败:${error}`)}
)
console.log(222)

执行的顺序
// 开始执行
// 111
// 222
// 执行失败:Error: 走catch
</script>

【6】async使用

<script setup>

        /* 
        async 用于标识函数的
            1. async标识函数后,async函数的返回值会变成一个promise对象
            2. 如果函数内部返回的数据是一个非promise对象,async函数的结果会返回一个成功状态 promise对象
            3. 如果函数内部返回的是一个promise对象,则async函数返回的状态与结果由该对象决定
            4. 如果函数内部抛出的是一个异常,则async函数返回的是一个失败的promise对象

        */
    
async function function1(){
  // return 2  // 走,then
  //throw new Error("异常状态,走catch") // 走,then
  // let promise = Promise.resolve("成功状态,走then") // 走,then
  let promise = Promise.reject("失败状态,走catch")  // 走,catch
  return  promise

}
// async函数,只要执行,就是promise对象
let promise=function1()

console.log(1111)

// 是promise对象就可以then和catch
promise.then(function(value){
  console.log(`value:${value}`)
}).catch(function (error){
  console.log(`error:${error}`)
})

console.log(2222)

//#########执行顺序
// 1111
// 2222
// error:失败状态,走catch
</script>

【7】 async+await使用

# async 和 await 是 JavaScript 中用于处理异步操作的语法糖,使得异步代码更简洁、更易读。它们是基于 Promises 的一种写法,能够简化异步操作的管理

# async:使用 async 关键字声明一个函数,这样函数会返回一个 Promise。即使函数内部返回的值不是 Promise,它也会被自动包装成 Promise

# await: 等待异步操作:在 async 函数内部,使用 await 关键字来等待一个 Promise 被解决(fulfilled)或拒绝(rejected)。await 会暂停函数的执行,直到 Promise 被解决,并返回结果

# async 关键字:声明一个异步函数,函数返回一个 Promise。
# await 关键字:暂停 async 函数的执行,等待 Promise 解决,并返回其结果。
  • 使用
<script setup>

/*
        1. await右侧的表达式一般为一个promise对象,但是也可以是一个其他值
        2. 如果表达式是promise对象,await返回的是promise成功的值
        3. await会等右边的promise对象执行结束,然后再获取结果,后续代码也会等待await的执行
        4. 如果表达式是其他值,则直接返回该值
        5. await必须在async函数中,但是async函数中可以没有await
        6. 如果await右边的promise失败了,就会抛出异常,可以通过 try ... catch捕获处理
    */

import axios from "axios";

async function function1() {
  try {
    // 好处就是,可以一次性发多个,挨个执行
    // 请求正确,会继续执行,不正确走,catch
    let res = await axios.get('http://localhost:8000/api/v1/films/film/')
    // let res1=await axios.get('...')
    // let res2=await axios.get('...')
    // 成功的话,就继续执行,可以进行页面的赋值
        // ...
    console.log(res.data.result)
  } catch (error) {
    // 请求出错就会走这里
    console.log(error.message)
  }
}

// 也可以这样写
// async function function1() {
//
//   // 好处就是,可以一次性发多个,挨个执行
//   // 请求正确,会继续执行,不正确走,catch
//   let res = await axios.get('http://localhost:8000/api/v1/films/film/')
//   // let res=await axios.get('...')
//   // let res=await axios.get('...')
//   console.log(res.data.result)
//
// }

function1()
</script>

【九】vue-roter

【1】使用

#####使用vue-roter,需要安装----需要安装4版本以上
cnpm install vue-roter@4 -S

【2】vue3用vite需要自己配

###需要自己创建文件夹router,文件index.js:都是这样命名的

#安装好之后router之后,进index.js中配置
	- import { createRouter, createWebHistory } from 'vue-router';
	- import HomeView from '../views/HomeView.vue'
        -  路由配置
        - const routes = [
                // 首页路径
                { path: '/', component: HomeView },
            ];
        - const router = createRouter({
            history: createWebHistory(),   // 使用什么模式
            routes // 路由配置
        })
        - export default router;
  # 在mian.js中配置
	- import router from './router';
    - createApp(App).use(router).use(ElementPlus).mount('#app');

# 

【3】路由跳转

# 不是这样得了:this.$route   this.$router

# 变了:
import {useRouter, useRoute} from 'vue-router'
# 提供对 Vue Router 实例的访问,使你能够进行编程式导航。
# 路由跳转
let router=useRouter()
router.push('/friend')
# 提供对当前路由信息的访问,包括路由路径、查询参数、路由参数等
# 获得路由中的数据
let route=useRoute()
console.log(route.path);    // 当前路由路径
console.log(route.query);   // 当前路由的查询参数
console.log(route.params);  // 当前路由的路由参数

【4】前置路由守护

router.beforeEach((to, from, next) => {
    //to 是目标地包装对象  .path属性可以获取地址
    //from 是来源地包装对象 .path属性可以获取地址
    //next是方法,不调用默认拦截! next() 放行,直接到达目标组件
    //next('/地址')可以转发到其他地址,到达目标组件前会再次经过前置路由守卫
    console.log(to.path, from.path, next)

    //需要判断,注意避免无限重定向
    if (to.name == 'home' || to.name == 'login') {
        next()
    } else {
        let token = localStorage.getItem('token')
        if (token) {
            next()
        } else {
            next('/login')
        }
    }
})

【十】pinia

  • 前言
# Pinia 是一个现代的 Vue 状态管理库,提供了更简洁和高效的方式来管理应用状态。它与 Vue 3 的组合式 API 紧密集成,支持 TypeScript,具备清晰的 API 和强大的功能,适合用于大型 Vue 应用的状态管理。

# 如何实现多个组件之间的数据传递?
    - 方式1 组件传参
    - 方式2 路由传参
    - 方式3 通过pinia状态管理定义共享数据
# 官网:https://pinia.vuejs.org/zh/introduction.html

# pinia和vuex的区别不大,可以说是没有区别
  • 使用
# 安装:cnpm install pinia -S

# 在main.js中配置
	- 

# 创建文件夹--store--文件名字可以随便定义,可以创建多个

#########使用:store/home.js
//defineStore 函数用于创建一个新的 store,这个 store 可以包含应用的状态、getter 和 actions。store 是 Pinia 用来集中管理状态的容器
import {defineStore} from 'pinia'

// 名字尽量定义成'defined组件名',
export const definedHome = defineStore({
    id: 'homePinia',  //这的id必须唯一
    // 这里面用于定义 数据,return返回出去
    // 对应的是一个对象
    state: () => {
        return {
            username: 'lsk',
            age: 22,
            hobby: ['sing', 'dance']
        }
    },
    // 用于定义一些通过数据计算而得到结果的一些方法 一般在此处不做对数据的修改操作
    getters: {
        // 计算hobby的长度
        getHobbyLength() {
            return this.hobby.length
        },
        // 让age每次访问+1
        getAge() {
            return this.age
        }
    },
    actions: {
        // 访问doubleAge年龄翻倍
        doubleAge() {
            this.age = this.age * 2
        }
    }
})

###########main.js中配置
// pinia状态管理器配置
import {createPinia} from 'pinia'
// 创建一个pinia对象
let pinia=createPinia()

createApp(App).use(router).use(ElementPlus).use(pinia).mount('#app');

#########:views/HomeView.vue
<script setup>
// 导入你创建的pinia状态管理器
import {definedHome} from "../store/home";
// 得到对象
let home=definedHome()

let getHobbyLength=home.getHobbyLength;
const handleDoubleAge=()=>{
  home.doubleAge()
}

</script>

<template>
  <h2>{{home.username}}</h2>
  <h2>{{home.age}}</h2>
  <button @click="handleDoubleAge">点击年龄+1</button>
<!--  // getters计算属性,先赋值在使用-->
  <h2>{{getHobbyLength}}</h2>
<!--  或者是直接使用-->
  <h2>{{home.getHobbyLength}}</h2>
  <h3>{{home.getAge}}</h3>

</template>

<style scoped>

</style>
  • 总结
####在组件中使用
// pinia状态管理器配置
import {createPinia} from 'pinia'
// 创建一个pinia对象
let pinia=createPinia()

######在组件中使用getters里面的方法,里面都是计算属性
直接使用:<h2>{{home.getHobbyLength}}</h2>
赋值使用:let getHobbyLength=home.getHobbyLength;<h2>{{getHobbyLength}}</h2>


#####在组件中使用state
  <h2>{{home.username}}</h2>
  <h2>{{home.age}}</h2>

######使用actions
const handleDoubleAge=()=>{
  home.doubleAge()
}
  <button @click="handleDoubleAge">点击年龄+1</button>

【十一】elementui-plus

# elementui-plus网址:https://element-plus.org/zh-CN/component/popover.html
# 安装
npm install element-plus -S

# 在main.js中配置
# vue3 用不了element-ui的,中可以用element-plus
import ElementPlus from 'element-plus'
# 还要引入
import 'element-plus/dist/index.css'

createApp(App).use(router).use(ElementPlus).mount('#app');

【作业】

# 1 把讲的写一下
# 2 之前在vue2上生命周期钩子函数案例
	-vue3 组合式写法
# 3 拓展
	-使用vite创建项目---》把vue-router集成到vue3中

    
# 4 vuex继承
# 5 使用pinia做状态管理器
	store

rom “…/store/home”;
// 得到对象
let home=definedHome()

let getHobbyLength=home.getHobbyLength;
const handleDoubleAge=()=>{
home.doubleAge()
}

{{home.username}}

{{home.age}}


- 总结

````python
####在组件中使用
// pinia状态管理器配置
import {createPinia} from 'pinia'
// 创建一个pinia对象
let pinia=createPinia()

######在组件中使用getters里面的方法,里面都是计算属性
直接使用:<h2>{{home.getHobbyLength}}</h2>
赋值使用:let getHobbyLength=home.getHobbyLength;<h2>{{getHobbyLength}}</h2>


#####在组件中使用state
  <h2>{{home.username}}</h2>
  <h2>{{home.age}}</h2>

######使用actions
const handleDoubleAge=()=>{
  home.doubleAge()
}
  <button @click="handleDoubleAge">点击年龄+1</button>

【十一】elementui-plus

# elementui-plus网址:https://element-plus.org/zh-CN/component/popover.html
# 安装
npm install element-plus -S

# 在main.js中配置
# vue3 用不了element-ui的,中可以用element-plus
import ElementPlus from 'element-plus'
# 还要引入
import 'element-plus/dist/index.css'

createApp(App).use(router).use(ElementPlus).mount('#app');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值