一、组合式API
- 前提环境条件:Node.js(16.0版本及以上)
- create-vue(Vue官方新的脚手架工具),底层切换到了Vite(下一代前端工具链)创建项目:npm init vue@latest
- npm install安装所需依赖
- npm run dev启动项目
1.1 setup入口
setup选项执行时机:beforeCreate钩子之前自动执行;setup定义数据+函数,然后以对象方式return;<script setup>
语法糖:可以更简单的使用组合式API(不需要export default、return、局部组件无需注册直接引入就可以使用等);setup中无this(原来指向组件实例),指向undefined。
1.2 reactive和ref函数
- reactive():接受对象类型数据的参数传入并返回一个响应式的对象。
(1)从vue包中导入reactive函数,import { reactive } from ‘vue’;
(2)在<script setup>
中执行reactive函数并传入类型为对象的初始值,并使用变量接收返回值。 - ref():接收简单类型或者对象类型的数据传入并返回一个响应式的对象。
(1)从vue包中导入reactive函数,import { ref } from ‘vue’;
(2)在<script setup>
中执行ref函数并传入初始值,使用变量接收ref函数的返回值。必须通过.value访问修改,且内部依赖于reactive函数。
1.3 computed计算属性函数
计算属性中不应该有副作用(如异步请求,修改dom)、避免直接修改计算属性的值(计算属性应该是只读的)
- 导入computed函数,import { computed } from ‘vue’;
- 执行函数在回调参数中return基于响应式数据做计算的值,用变量接收。
1.4 watch监听函数
watch函数用于侦听一个或者多个数据的变化,数据变化时执行回调函数。
- 监听单个数据
(1)导入watch函数,import { watch } from ‘vue’;
(2)执行watch函数出入要侦听的响应式数据(ref对象,第一个参数不需要使用value)和回调函数。watch(count, (newValue, oldValue) => { console.log("count变化了", newValue, oldValue) })
- 监听多个数据:同时侦听多个响应式数据的变化,不管哪个数据变化都需要执行回调,用列表表示。
watch([count, name], ([newCount, newName], [oldCount, oldName]) => { console.log("count或name变化了", [newCount, newName], [oldCount, oldName]) })
- immediate:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调。
watch(count, () => { console.log("count变化了") }, { //第三个参数 immediate: true })
- deep:默认机制:通过watch监听的ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep选项(有损耗,尽量不用)。
const state = ref({ count: 0 }) watch(state, () => { console.log("count变化了") }, { deep: true //深度侦听 })
- 精确侦听对象的某个属性
watch( () => state.value.age, //精确监听age属性 () => { console.log("age发生变化") } )
1.5 生命周期函数
生命周期函数基本使用:导入生命周期函数,执行生命周期函数,传入回调。生命周期函数是可以执行多次的,多次执行时传入的回调会在时机成熟时依次执行。
1.6 父子通信
- 父传子
(1)父组件在子组件标签中绑定属性(count为响应式数据,message为静态数据)
(2)子组件通过defineProps(编译器宏)接收传递的数据<Son :count="count" message="father message" />
const props = defineProps({ message: String, count: Number })
- 子传父
(1)父组件在子组件标签中绑定事件@,定义对应的方法,方法的参数用于接收子组件传递的参数
(2)子组件通过defineEmits编译器宏生成emit方法,子组件触发自定义事件,并向父组件传递参数<Son @getMessage="getMessage" />
const emit = defineEmits(['getMessage']) //可以有多个 const sendMsg = () => { //子组件定义的方法,触发就会传递参数 emit('getMessage', '向父组件传递的消息') }
1.7 模板引用
通过ref标识获取真实的dom对象或者组件实例对象。
(1)调用ref函数生成一个ref对象:const h1ref = ref(null)
(2)通过ref标识绑定ref对象到标签:<h1 ref="h1ref">Dom对象</h1>
(3)组件挂载完毕获取dom对象:onMounted(() => { console.log(h1ref.value) })
(4)默认情况下在script setup语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过defineExpose编译宏指定哪些属性和方法允许访问:defineExpose({ 组件要放开的属性和方法名 })
1.8 provide和inject
顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信。跨层传递方法:顶层组件可以向底层组件传递方法,底层组件调用方法间接修改顶层组件中的数据。
- 顶层组件通过provide函数提供数据
import { provide } from 'vue'; provide("参数名", 值); //值可以为响应式数据,也可以是方法名
- 底层组件通过inject函数获取数据
import { provide } from 'vue'; const 参数名 = inject("参数名");
二、Pinia
Pinia是Vue的专属的最新状态管理库,是Vuex状态管理工具的替代品。提供更加简单的API(去掉了mutation);提供符合组合式风格的API(和Vue3新语法统一);去掉了modules的概念,每一个store 都是一个独立的模块;搭配TypeScript一起使用提供可靠的类型推断。Pinia官网
- 添加Pinia到Vue
(1)npm install pinia
(2)在main.js中创建pinia实例并传递给其它应用import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' const pinia = createPinia() const app = createApp(App) app.use(pinia) app.mount('#app')
- 定义store官网
(1) 定义store // stores/counter.js import { defineStore } from 'pinia' import { computed, ref } from 'vue' import axios from 'axios' export const useCounterStore = defineStore('counter', () => { const count = ref(0) //ref() 就是 state 属性 function increment() { //function() 就是 actions count.value++ } // getter定义 const doubleCount = computed(() => count.value * 2) //computed() 就是 getters //异步action const getList = async () => { const res = await axios.get("https://www.baidu.com/") console.console.log(res.data); } return { count, increment, doubleCount, getList } }) (2) 使用store <script setup> import { useCounterStore } from '@/stores/counter' import { onMounted } from 'vue'; const counterStore = useCounterStore() onMounted(() => counterStore.getList()) </script> <template> <button @click="counterStore.increment">Current Count: {{ counterStore.count }} </button> </template>
- storeToRefs函数
使用storeToRefs函数可以辅助保持数据( state + getter)的响应式解构。即在使用store时,可以定义数据重新覆盖store,若想保持数据是响应式数据,则需用storeToRefs函数。方法则不需要使用storeToRefs就可以解析重构。import { storeToRefs } from 'pinia' const { count } = storeToRefs(counterStore) //此时count就可以代替原来的counterStore.count const { increment } = counterStore //increment代替原来的counterStore.increment
三、项目起步设置
- 项目文件夹管理
(1)apis:API接口文件夹
(2)composables:组合函数文件夹
(3)directives:全局指令文件夹
(4)styles:全局样式文件夹
(5)utils:工具函数文件夹 - 别名路径联想提示
在编写代码的过程中,一旦输入@/,VSCode会立刻联想出src下的所有子目录和文件,统一文件路径访问不容易出错。
(1)根目录下新增jsconfig.json文件
(2)添加json格式的配置项{ "compilerOptions": { "baseUrl": "./", "paths": { "@/*": [ "src/*" ] } } }
- ElementPlus按需导入官网
- axios基础配置官网
先npm install axios,配置基础实例(统一接口配置)import axios from 'axios' const httpInstance = axios.create({ //axios.create()方法可以执行多次,每次执行就会生成一个新实例 baseURL: 'http://localhost:8081/', timeout: 5000 }) //请求拦截器 httpInstance.interceptors.request.use( config => { return config; }, error => Promise.reject(error) ) //响应拦截器 httpInstance.interceptors.response.use( response => response.data, error => { return Promise.reject(error) } ) export default httpInstance; //导出网络请求
四、前端后台管理系统模板
vue3-elementplus-admin纯框架(登录和主页面):基于 vue3.x + CompositionAPI setup 语法糖 + typescript + vite + element plus + vue-router+ pinia 技术