Vue3基础入门

Vue3基础

选项式 API

组件的初始化还是和Vue2那样

<template>
    <!-- 可以有多个根元素 -->
    <div>当前鼠标位置</div>
    <div>x: {{ mouse.x }}</div>
    <div>y: {{ mouse.y }}</div>
    <div>当前点击次数:{{ count }}</div>
    <button @click="add">点击</button>
</template>

<script>
export default {
    // vue2 中采用的是 options API
    // 常见的配置项: data created methods watch computed components
    data() {
        return {
            mouse: {
                x: 100,
                y: 100,

            },
            count: 0
        }
    },
    mounted() {
        document.addEventListener("mousemove", this.mouseMove)
    },
    // vue2 叫 destroyed
    destroyed() {
        document.removeEventListener("mousemove", this.mouseMove)
    },
    methods: {
        add() {
            this.count++
        },
        mouseMove(e) {
            this.mouse.x = e.clientX
            this.mouse.y = e.clientY
        }
    }
}
</script>

组合式API

eg:

<template>
  <!-- 可以有多个根元素 -->
  <div>当前鼠标位置</div>
  <div>x: {{ mouse.x }}</div>
  <div>y: {{ mouse.y }}</div>
  <div>当前点击次数:{{ count }}</div>
  <button @click="add">点击</button>
</template>

<script>
import { onMounted, onUnmounted, reactive, ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const add = () => {
      count.value++
    }

    const mouse = reactive({
      x: 0,
      y: 0,
    })

    const move = (e) => {
      mouse.x = e.pageX
      mouse.y = e.pageY
    }
    onMounted(() => {
      document.addEventListener('mousemove', move)
    })
    onUnmounted(() => {
      document.removeEventListener('mousemove', move)
    })
    return {
      count,
      add,
      mouse,
    }
  },
}
</script>

代码抽离—hooks 钩子函数
import { ref, reactive, onMounted, onUnmounted } from 'vue'

//  抽离---hooks 钩子函数
// 业务 A
const useCount = () => {
  const count = ref(0)
  const add = () => {
    count.value++
  }
  onMounted(() => {
    // ❗✅多个生命周期,不会被合并
    console.log('业务 A 生命周期')
  })
  return { count, add }
}
// 业务 B
const useMouseMove = () => {
  const mouse = reactive({ x: 100, y: 100 })
  const mouseMove = e => {
    mouse.x = e.clientX
    mouse.y = e.clientY
  }
  onMounted(() => {
    document.addEventListener('mousemove', mouseMove)
  })
  onUnmounted(() => {
    document.removeEventListener('mousemove', mouseMove)
  })
  return { mouse }
}

export default {
  setup() {
    const { count, add } = useCount()
    const { mouse } = useMouseMove()
    return { count, add, mouse }
  }
}

Vue3生命周期图示

在这里插入图片描述

请添加图片描述
❗✅多个生命周期,不会被合并

setup 函数

setup 函数是 Vue3 特有的选项,作为组合式API的起点,注意以下三点:
  1. 从组件生命周期看,它在 beforeCreate 之前执行
  2. 函数中 this 不是组件实例,是 undefined
  3. ✨如果数据或者函数在模板中使用,需要在 setup 返回
经验:

今后在vue3的项目中几乎用不到 this

reactive 函数

只能用于复杂类型数据,数组类型也不建议用

1. 导入 reactive 函数
import { reactive } from 'vue'
2. 通过 reactive 函数包装成响应式对象
const obj = reactive({
    name:'zs',
    age:18
})

const btn = () => {
    obj.age++
}
3. 返回给模板使用
return { obj,btn }

组合式API-ref函数

ref 函数,可以把任意类型数据转换成响应式。

  1. vue 中导入 ref 函数
  2. setup 函数中,使用 ref 函数包装成响应式数据(不分类型)
  3. 最后 setup 函数返回一个对象,包含该响应式数据即可
❗使用 ref 的两个注意点:
  1. <script> 中需要 .value

  2. <template> 会自动解套,不需要 .value

script setup 语法糖✨

不需要在setup函数里面写代码了,不需要 return,vue3 自动返回,直接变成:

<script setup>
import { onMounted, onUnmounted, reactive, ref } from 'vue'

let mouse = reactive({ x: 100, y: 100 })
function mouseMove(e) {
  mouse.x = e.clientX
  mouse.y = e.clientY
}

let count = ref(0)
const add = () => {
  count.value++
}
onMounted(() => {
  document.addEventListener('mousemove', mouseMove)
})

onUnmounted(() => {
  document.removeEventListener('mousemove', mouseMove)
})
</script>

computed 函数

  1. 导入 computed 函数 import {computed} from 'vue'

  2. 调用 computed 函数并传入一个回调函数 const computedRes = computed(() => { return xx})

  3. 函数内部记得 return 返回结果

const nextAge = computed(() => {
  return age.value + 1
})
computed 函数的另一个写法
const nextAge2 = computed({
  get() {
    return age.value + 2
  },
  set(value) {
    age.value = value - 2
  }
})

watch 函数

watch 参数
  1. 被监听的数据

  2. 回调函数

  3. 配置项(可选)

基本写法
基础类型
import { ref,watch } from 'vue'
const money = ref(1400)
watch(money,() => {
    console.log('钱变化了', money.value)
})
复杂类型
const arr = JSON.parse(localStorage.getItem('todoVue3')) || [
  { id: 1, content: 'eat', done: true },
  { id: 2, content: 'play', done: false },
]

const list = ref(arr)

watch(list,() => {
  localStorage.setItem('todoVue3', JSON.stringify(list.value))

},{
    deep:true,
    immediate:true
}
     )
进阶写法
基础类型
import { ref,watch } from 'vue'
const money = ref(1400)
watch(money,(newVal,oldVal) => {
    console.log('钱变化了',newVal,oldVal)
})
复杂类型

不常用,✨工作经验:一般是一个watch 监听一个值,监听对象属性的话建议监听整个属性(但是监听整个对象newValue 此处和 oldValue 是相等的,因为它们是同一个对象)

通过 getters 函数写法,可以侦听对象的某个属性

通过数组,可同时侦听多个数据

watch(
    [()=> obj.value.age,() => obj.value.cp.age],
    (newVal,oldVal){
      console.log('obj变化了',newVal,oldVal)
    },
    {
        deep:true
    }    
)

模板ref

获取DOM元素
  1. 创建 ref const hRef = ref(null)

  2. 模板 ref 建立关联 <h1 ref="hRef"></h1>

  3. 组件挂载完毕后可以访问 DOM节点 onmounted { hRfe.value }

应用场景
//需求:获取输入框焦点
const iptRef = ref(null)

<input ref="inputRef" type="text" />
    
const focusClick = () =>{
    iptRef.value.focus()
}   

// 需求:获取输入框焦点
<audio ref="audioRef" controls>
    audioRef.value.play()
❗获取组件的 DOM 元素的注意点
  • 父组件想使用子组件的方法需要子组件用defineExpose主动暴露方法
代码实现

const sayHi = () => {
  console.log('sayHi~')
}
// 暴露 方法
defineExpose({ sayHi })

// script
const footerRef = ref(null)
const clickBtn = () => {
  sonRef.value.sayHi()
}
// template
<Son ref="sonRef"/>

父传子

基本结构

在 script 中用defineProps获取 props

// father:
const money = ref(100)
<Children :money="money">

// son:    
<script setup>
// 在 script 中获取 props
const props = defineProps({
    money:Number,
    car:{
    	type:String,
    	default:'宝马'
    }
})

console.log('在script中获取props', props.money)
</script>

子传父 defineEmits

<ChildCom @change-money="changeMoneyFn" :money="money"></ChildCom>

定义 emit ,显式声明事件名称

const emits = defaultEmits(['changeMoney'])

const btn = () => {
    emit('changeMoney',100) // ❗注意没有 this
}
// @click="emits('changeMoney')"

跨组件通讯

provide 提供数据

每个 provide 提供一个数据,可重复使用

provide('count',count)

inject 获取数据

每个 inject 接收一个数据,可重复使用

const count = inject('count')

辅助函数toRefs

const user = reactive({ name:'zg',age:80 })

const res = toRfes(user)

把 obj 的每一个属性都变成独立的 ref 对象,所以解构出来的每个属性都是响应式的 ref

const { name,age } = toRefs(user)

核心库

vue-router

基础使用

安装 npm i vue-router@4 --save

导入 创建路由实例的函数 和 创建哈希模式(createWebHashHistory )历史模式(createWebHistory) 的函数

import { createRouter,createWebHashHistory } form 'vue-router'

// 创建路由实例

const router = createRouter({
	// vue2 mode:'hash'
    history:createWebHashHistory,
    routes:[]
})
export default router

挂载路由:

main.js

import router from './router'

// 以插件形式使用 router
const app = createApp(App)
app.use(router)
app.mount('#app')
路由配置和路由组件

在路由实例的 路由表

routes: [
    { path: '/home', component: () => import('../views/HomePage.vue') },
    { path: '/login', component: () => import('../views/LoginPage.vue') },
  ],

路由链接与路由出口

<router-link> <router-view>

vue-router-组合式API

因为我们在 setup 里面没有访问 this,所以我们不能再直接访问 this.$router

或 this.$route

使用 useRouteruseRoute 函数:

import { useRouter,useRoute } from 'vue-router'

获取全局路由实例

const router = useRouter()

获取当前路由信息

const route = useRoute()

使用:

router.push('/home')

route.query/route.path/route.fullPath/route.params
✨非组件跳转页面方法:

❌useRouter 使用有限制,只能使用于 setup 组合式 API 内

// 非组件中,可通过导入路由实例,用于实现页面跳转
import router from '@/router';
 // const router = useRouter();
 // console.log(22, router);   // undefined
 // router.push('/');
 // ✅非组件直接导入路由实例 import router from '@/router';
  router.push('/');

pinia

Pinia 是 Vue.js 的轻量级状态管理库

官方网站

中文文档(非官方,翻译了大部分内容)

为什么学习pinia?
  • pinia和vuex4一样,也是vue官方的状态管理工具(作者是 Vue 核心团队成员)
  • pinia相比vuex4,对于vue3的兼容性更好
  • pinia相比vuex4,具备完善的类型推荐
  • pinia同样支持vue开发者工具,最新的开发者工具对vuex4支持不好
  • Pinia 的 API 设计非常接近 Vuex 5提案
基础使用
安装 npm i pinia@2 --save
main.js中挂载
import { createPinia  } from 'pinia'
app.use(createPinia())
pinia 的 store

三个概念,stategettersactions,可以假设这些概念相当于组件中的 data、 computed 和 methods。

✨pinia没有mutation,用起来更加方便

pinia 支持两种 API 风格:
  1. defineStore('唯一标识',选项式API配置)
  2. defineStore('唯一标识', 组合式API函数)

返回值是一个用于获取 store 的函数

建议命名规范:useXxxStore

export const useCounterStore = defineStore('counter',{
    state:() => { return { count:0 }}
})
使用
import { useCounterStore } from './store/counter'
// 调用获取 store 的函数
const counterStore = useCounterStore()

{{ counterStore.count }}
选项式API写法
state:()=>{
	// 建议 vue2、vue3 都在state return 一个对象
    return { count:100 }
}

// getters 看做 computed
  getters: {
    doubleCount() {
      // ❗❗不用再写state,通过 this 使用即可
      return this.count * 2
    },
  },
      
// 使用  {{ counterStore.doubleCount }}    
      

// actions 看做 methods,支持同步和异步,传参也很方便
  actions: {
    // 支持同步
    addCount(val) {
      this.count += val
    },
    // 支持异步
    addCountASync() {
      setTimeout(() => {
        this.count++
      }, 1000)
    },
  },
      
// 使用  @click="couterStore.addCount(10)"    

❗state 与 getters 同名,以 getters 的为准

组合式API写法
import { defineStore } from 'pinia'
import { computed,ref } from 'vue'

export const useMoneyStore = defineStore('money',()=>{
    // state
    const salary = ref(1400)
    // getters
    const doubleSalary = computed(()=> saraly.value*2)
    // actions
    const addSalaryAsync = () =>{
        setTomeout(()=>{
            salary.value++
        },1000)
    }
    // actions
    const addSalary = (val)=>{
        salary.value += val
    }
    // 🚨 注意:要使用的数据或方法,记得通过 return 返回
    return {salary,doubleSalary,addSalaryAsync}
})
辅助函数storeToRefs

简化使用 store

❌解构出的方法用不了
✅✨工作经验:不使用 storeToRefs,直接使用 toRefs 就行,只不过官网上有,介绍一下而已

import { storeToRefs } from 'pinia'
import { useMoneyStore } from './store/money'

const moneyStore = useMoneyStore()

❌直接解构数据会失去响应式
// const { salary,doubleSalary }  = moneyStore

✅storeToRefs 解构后还支持响应式
const { salary,doubleSalary } = storeToRefs(moneyStore)

使用:{{ salary }} {{ doubleSalary }}

合并模块管理

从合并管理的模块中导入所需的 store

src/store/index.js
// 导出模块合集
export * from './modules/counter'
export * from './modules/money'
App.vue

import { useCounterStore,useMoneyStore } from './store'

不用分别从 ./store/counter./store/money中导入

TodoList案例

store return 回去时记得+{ }
…未完待续

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue 3 是一款流行的 JavaScript 框架,用于构建交互式的用户界面。下面是一个简单的 Vue 3 入门基础教程: 1. 安装 Vue 3:你可以通过使用 npm 或 yarn 在你的项目中安装 Vue 3。在命令行中运行以下命令来进行安装: ``` npm install vue@next ``` 或者 ``` yarn add vue@next ``` 2. 创建 Vue 实例:在你的 HTML 文件中,引入 Vue 库,并创建一个新的 Vue 实例。可以在实例化时指定选项对象来配置 Vue 实例。例如: ```javascript <html> <head> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> {{ message }} </div> <script> const app = Vue.createApp({ data() { return { message: 'Hello, Vue 3!' }; } }).mount('#app'); </script> </body> </html> ``` 3. 数据绑定:Vue 3 支持使用双大括号语法将数据绑定到 HTML 模板中。在上面的示例中,`message` 数据绑定到了 `<div>` 元素中。 4. 计算属性:Vue 3 还提供了计算属性的特性,用于在模板中动态计算一些值。可以通过定义 `computed` 对象来创建计算属性。例如: ```javascript const app = Vue.createApp({ data() { return { firstName: 'John', lastName: 'Doe' }; }, computed: { fullName() { return this.firstName + ' ' + this.lastName; } } }).mount('#app'); ``` 在模板中,你可以直接使用 `fullName` 计算属性。 这只是一个简单的入门教程,Vue 3 还有很多其他功能和概念,例如组件、指令、事件处理等。你可以查阅 Vue 3 的官方文档以获得更详细的了解和学习资源。祝你学习愉快!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wendyymei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值