vue3 常用命令,函数,插件,创建命令
1.vu3 基本命令:
v-model
v-if
v-else
v-binding
v-for
v-show
2.setup 函数
第一步安装:npm i vite-plugin-vue-setup-extend -D
第二步配置:vite.config.ts
import { defineConfig } from 'vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
export default defineConfig({
plugins: [ VueSetupExtend() ]
})
第三步使用:<script setup lang="ts" name="Person">
import {ref} from 'vue'
let name1 = '张三' //不是响应式的了
let name2 = ref('张三') //是响应式的了
3. ref 响应式函数
作用:定义响应式变量,基本数据类型做为入参
语法:let xxx = ref(初始值)
返回值:一个RefImpl的实例对象,简称ref对象或ref,ref对象的value属性是响应式的
注意点:
JS中操作数据需要:xxx.value,但模板中不需要.value,直接使用即可
对于let name = ref('张三')来说,name不是响应式的,name.value是响应式的
4.reactive响应式函数
作用:定义响应式变量,对象类型做为入参
语法:let xxx = reactive(源对象)
返回值:一个Proxy的实例对象
注意点:
reactive定义的响应式数据是“深层次”的。
5. ref vs reactive
ref用来定义:基本类型数据、对象类型数据
reactive用来定义:对象类型数据
ref创建的变量必须使用.value(可以使用volar插件自动添加.value)
reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)Object.assgin(car,{barnd:'小米',price:30}
6.toRefs,toRef
作用:
将一个响应式对象中的每一个属性,转换为ref对象
toRefs与toRef功能一致,但toRefs可以批量转换
import {ref,reactive,toRefs,toRef} from 'vue'
// 数据
let person = reactive({name:'张三', age:18, gender:'男'})
let {name,gender} = toRefs(person) //toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力
let age = toRef(person,'age') //通过toRef将person对象中的age 1个属性取出,且依然保持响应式的能力
7.computed
作用:
根据已有数据计算出新数据(和Vue2中的computed作用一致)
计算属性有缓存,方法没缓存
import {ref,computed} from 'vue'
let firstName = ref('zhang')
let lastName = ref('san')
// 计算属性——只读取,不修改
/* let fullName = computed(()=>{
return firstName.value + '-' + lastName.value
}) */
// 计算属性——既读取又修改
let fullName = computed({
// 读取
get(){
return firstName.value + '-' + lastName.value
},
// 修改
set(val){
console.log('有人修改了fullName',val)
firstName.value = val.split('-')[0]
lastName.value = val.split('-')[1]
}
})
8.watch
作用:监视数据的变化(和Vue2中的watch作用一致)
特点:Vue3中的watch只能监视以下四种数据
1. ref定义的数据。
2. reactive定义的数据。
3. 函数返回一个值(getter函数)。
4. 一个包含上述内容的数组。
import {ref,reactive,watch} from 'vue'
// 数据
let sum = ref(0)
// 方法
function changeSum(){
sum.value += 1
}
// 监视,情况一:监视【ref】定义的【基本类型】数据
const stopWatch = watch(sum,(newValue,oldValue)=>{
if(newValue >= 10){
stopWatch()
}
})
let person = ref({
name:'张三',
age:18
})
function changeAge(){
person.value.age += 1
}
function changePerson(){
person.value = {name:'李四',age:90}
}
//监视【ref】定义的【对象类型】数据
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{deep:true})
let person = reactive({
name:'张三',
age:18
})
function changePerson(){
Object.assign(person,{name:'李四',age:80})
}
// 监视,情况三:监视【reactive】定义的【对象类型】数据,且默认是开启深度监视的
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
})
// 监视,情况四:监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,更推荐写函数
watch(()=>person.car,(newValue,oldValue)=>{
console.log('person.car变化了',newValue,oldValue)
},{deep:true})
// 监视,情况五:监视上述的多个数据
watch([()=>person.name,person.car],(newValue,oldValue)=>{
console.log('person.car变化了',newValue,oldValue)
},{deep:true})
9.watch vs watchEffect
watch:要明确指出监视的数据入参
watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)
import {ref,watch,watchEffect} from 'vue'
// 数据
let temp = ref(0)
let height = ref(0)
// 用watch实现,需要明确的指出要监视:temp、height
watch([temp,height],(value)=>{
const [newTemp,newHeight] = value
// 室温达到50℃,或水位达到20cm,立刻联系服务器
if(newTemp >= 50 || newHeight >= 20){
console.log('联系服务器')
}
})
// 用watchEffect实现,不用
const stopWtach = watchEffect(()=>{
// 水温达到100,或水位达到50,取消监视
if(temp.value === 100 || height.value === 50){
console.log('清理了')
stopWtach()
}
})
10. vue3生命周期
让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子
创建阶段:setup
挂载阶段:onBeforeMount、onMounted
更新阶段:onBeforeUpdate、onUpdated
卸载阶段:onBeforeUnmount、onUnmounted
常用的钩子:onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前)
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
// 数据
let sum = ref(0)
// 方法
function changeSum() {
sum.value += 1
}
console.log('setup')
// 生命周期钩子
onBeforeMount(()=>{
console.log('挂载之前')
})
onMounted(()=>{
console.log('挂载完毕')
})
onBeforeUpdate(()=>{
console.log('更新之前')
})
onUpdated(()=>{
console.log('更新完毕')
})
onBeforeUnmount(()=>{
console.log('卸载之前')
})
onUnmounted(()=>{
console.log('卸载完毕')
})
11. 自定义函数:hook:
优势:复用代码, 让setup中的逻辑更清楚易懂
useDog.ts
import {reactive,onMounted} from 'vue'
import axios,{AxiosError} from 'axios'
export default function(){
let dogList = reactive<string[]>([])
// 方法
async function getDog(){
try {
// 发请求
let {data} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')
// 维护数据
dogList.push(data.message)
} catch (error) {
// 处理错误
const err = <AxiosError>error
console.log(err.message)
}
}
// 挂载钩子
onMounted(()=>{
getDog()
})
//向外部暴露数据
return {dogList,getDog}
}
1.hook的使用demo: http.js(axios+拦截器)
// axios基础的封装
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/stores/userStore'
const httpInstance = axios.create({
baseURL: 'http://webapi.net',
timeout: 5000
})
// 拦截器
// axios请求拦截器
httpInstance.interceptors.request.use(config => {
// 1. 从pinia获取token数据
const userStore = useUserStore()
// 2. 按照后端的要求拼接token数据
const token = userStore.userInfo.token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
}, e => Promise.reject(e))
// axios响应式拦截器
httpInstance.interceptors.response.use(res => res.data, e => {
// 统一错误提示
ElMessage({
type: 'warning',
message: e.response.data.message
})
return Promise.reject(e)
})
//导出实列对象
export default httpInstance
2.user.js
// 封装所有和用户相关的接口函数
import httpInstance from '@/utils/http'
export const loginAPI = ({ account, password }) => {
return httpInstance({
url: '/login',
method: 'POST',
data: { //post
account,
password
}
})
}
3.category.js
import request from '@/utils/http'
export function getCategoryAPI (id) {
return request({
url: '/category',
params: { //get
id
}
})
}
4.user.js 标准写法
import {reactive,onMounted} from 'vue'
import axios,{AxiosError} from 'axios'
export default function(){
let dogList = reactive<string[]>([])
// 方法
async function getDog(){
try {
// 发请求
let {data} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')
// 维护数据
dogList.push(data.message)
} catch (error) {
// 处理错误
const err = <AxiosError>error
console.log(err.message)
}
}
// 挂载钩子
onMounted(()=>{
getDog()
})
//向外部暴露数据
return {dogList,getDog}
}
12.路由的使用vue-router
1.配置路由文件
router/index.js
import {createRouter,createWebHistory} from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'
const router = createRouter({
history:createWebHistory(),
routes:[
{
path:'/home',
component:Home
},
{
path:'/about',
component:About
}
]
})
export default router
2.main.ts引用加载路由文件
import router from './router/index.js'
app.use(router)
app.mount('#app')
3.路由跳转: to字符串,to对象(to前需加冒号:
<RouterLink to='/home' >Home</RouterLink>
<RouterLink to="{ path: '/about'}">About</RouterLink>
4.路由的工作模式
history模式:createWebHistory
优点:URL更加美观,不带有#,更接近传统的网站URL。
缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404错误
const router = createRouter({
history: history: createWebHistory(), //web模式
})
hash模式:createWebHashHistory
优点:兼容性更好,因为不需要服务器端处理路径。
缺点:URL带有#不太美观,且在SEO优化方面相对较差
const router = createRouter({
history: createWebHashHistory(),
routes:[
{
name: 'zhuye', //命名路由 <router-link :to="{name:'zhuye'}">跳转</router-link>
path: '/home',
component: Home
},
{
name: 'xinwen',
path: '/news',
component: News,
children:[
{
name: 'xiang', // 命名 <router-link :to="{path:'/news/detail'}">跳转</router-link> =<router-link to="/news/detail">xxxx</router-link>
path: 'detail',
component: Detail,
}
]
}
]
})
export default router
5.1 路由传参:
<router-link to="/news/detail?a=1&b=2&content=欢迎你">
<RouterLink
:to="{
//name:'xiang', //用name也可以跳转
path:'/news/detail',
query:{ //params参数
id:news.id,
title:news.title,
content:news.content
}
}
5.2 query
5.2.1 query接收参数:
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印query参数
console.log(route.query)
5.2.2 params接收参数:
<RouterLink
:to="{
name:'xiang', //params传参,必须使用用name跳转,不能使用path
params:{
id:news.id,
title:news.title,
content:news.title
}
}
console.log(route.params)
6.路由的嵌套使用:children
7.跳转导航:
import {useRoute,useRouter} from 'vue-router'
const route = useRoute()
const router = useRouter()
console.log(route.query)
console.log(route.parmas)
console.log(router.push)
console.log(router.replace)
8.重定向redirect
{
path:'/',
redirect:'/about'
}
13.pinia的使用:分布式缓存:读取数据的工具,不用重复读取,只读一遍
第一步安装:npm install pinia
第二步:操作src/main.ts
/*引入createPinia,用于创建pinia */
import { createPinia } from 'pinia'
/* 创建pinia */
const pinia = createPinia()
const app = createApp(App)
/* 使用插件 */{}
app.use(pinia)
app.mount('#app')
1.存储+读取数据demo: storeCount.js
// 引入defineStore用于创建store
import {defineStore} from 'pinia'
// 定义并暴露一个store
export const useTalkStore = defineStore('talk',{
// 动作
actions:{},
// 状态
state(){
return {
talkList:[
{id:'yuysada01',content:'你今天有点怪,哪里怪?怪好看的!'},
{id:'yuysada02',content:'草莓、蓝莓、蔓越莓,你想我了没?'},
{id:'yuysada03',content:'心里给你留了一块地,我的死心塌地'}
]
}
},
// 计算
getters:{}
})
14.生成唯一id: nanoid
15.组件通信
15.1 父传子:
props
v-model
$refs
插槽
15.2 子传父:
props
v-model
$parent
15.3 祖传孙,孙传组:
$attrs
provide,inject
15.4 兄弟间,任意组件间:
mitt
pinia
组件通信:props,mitt,v-model,$attrs,$parent,provide,inject,pinia,slot插槽
16. hook的使用
16.1 useDog.ts
import {reactive,onMounted} from 'vue'
import axios,{AxiosError} from 'axios'
export default function(){
let dogList = reactive<string[]>([])
// 方法
async function getDog(){
try {
// 发请求
let {data} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')
// 维护数据
dogList.push(data.message)
} catch (error) {
// 处理错误
const err = <AxiosError>error
console.log(err.message)
}
}
// 挂载钩子
onMounted(()=>{
getDog()
})
//向外部暴露数据
return {dogList,getDog}
}
16.2 组件中具体使用*.vue:
<template>
<div>
dog:<img v-for="(u,index) in dogList" :key="index" :src="(u as string)" >
</div>
</template>
<script setup lang="ts">
import useDog from './stores/useDog'
let {dogList,getDog} = useDog()
console.log(dogList)
</script>
17.自动导入定制化样式文件进行样式覆盖
17.1 安装插件: pnpm install -D sass unplugin-vue-components unplugin-auto-import
17.2 添加src/css/index.scss 文件
// styles/element/index.scss
/* 只需要重写你需要的即可 */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': green,
),
'success': (
'base': #67c23a,
),
'warning': (
'base': #e6a23c,
),
'danger': (
'base': #f56c6c,
),
'error': (
'base': #f56c6c,
),
'info': (
'base': #909399,
)
)
);
17.2 引入vite.config.ts
// elementPlus按需导入
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [
// 1. 配置elementPlus采用sass样式配色系统
ElementPlusResolver({ importStyle: "sass" }),
],
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
css: {
preprocessorOptions: {
scss: {
// 2. 自动导入定制化样式文件进行样式覆盖
additionalData: `
@use "@/styles/element/index.scss" as *;
@use "@/styles/var.scss" as *;
`,
}
}
}
})
18.父组件使用子组件的数据:使用defineExpose传递
18.1.Person.vue
<!-- 子组件Person.vue中要使用defineExpose暴露内容 -->
<script lang="ts" setup name="Person">
import {ref,defineExpose} from 'vue'
// 数据
let name = ref('张三')
let age = ref(18)
// 使用defineExpose将组件中的数据交给外部
defineExpose({name,age})
</script>
18.2.app.vue 父组件使用子组件的数据
<!-- 父组件App.vue -->
<template>
<Person ref="ren"/>
<button @click="test">测试</button>
</template>
<script lang="ts" setup name="App">
import Person from './components/Person.vue'
import {ref} from 'vue'
let ren = ref()
function test(){
console.log(ren.value.name)
console.log(ren.value.age)
}
</script>
19.传参:query,params
query
params:name
<script setup lang="ts">
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印query参数
console.log(route.query)
console.log(route.params)
</script>
<template>
<div>
news page
</div>
<router-link :to="{
name:'xiang', //path:'/news/detail'=query,params必须用name跳转
params:{
id:1,
name:'zhangsan'
}
}">detail</router-link>
<div>
<RouterView></RouterView>
</div>
</template>
<style>
</style>
{
path:'/',
redirect:'/about'
}
20.pinia的使用:
20.1定义:talk.ts
// 引入defineStore用于创建store
import {defineStore} from 'pinia'
// 定义并暴露一个store
export const useTalkStore = defineStore('talk',{
// 动作
actions:{},
// 状态
state(){
return {
talkList:[
{id:'yuysada01',content:'你今天有点怪,哪里怪?怪好看的!'},
{id:'yuysada02',content:'草莓、蓝莓、蔓越莓,你想我了没?'},
{id:'yuysada03',content:'心里给你留了一块地,我的死心塌地'}
]
}
},
// 计算
getters:{}
})
20.2 使用pinia定义的数据:
<script setup lang="ts" name="Count">
import {useTalkStore} from '@/store/talk'
const talkStore = useTalkStore()
console.log(talkStore.talkList)
</script>
21.Icon图标的使用:
0.安装插件:pnpm install @element-plus/icons-vue
1.main.ts 引入插件
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
//全局注册
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
2.app.vue使用测试
2.1 复制icon
<el-icon size="35" color="red"><House /></el-icon>
2.1 引入
<script setup lang="ts">
import { Calendar, Search } from '@element-plus/icons-vue';
<el-icon size="35" color="red"><House /></el-icon>
<el-button type="primary" icon="Search">button</el-button>
<el-input placeholder="placeholder" :sufifix-icon="Calendar"></el-input>
<el-input placeholder="Please input" :suffix-icon="Calendar" :prefix-icon="Search"/>
二.常用插件:
pnpm install element-plus --save
pnpm i axios --save https请求
pnpm install vue-router
pnpm install -D unplugin-vue-components unplugin-auto-import按需导入(自动导入)
pnpm install @element-plus/icons-vue 使用element-plus Icon图标
npm install pinia
pnpm install sass
pnpm nanoid
极简插件
三.vue3 demovue
pnpm init vite@latest
pnpm create vue@latest
本地跨域配置