vue项目基础知识

本文详细解读了Vue3中的ScriptSetup语法,介绍了setup函数的执行时机,以及reusablefunctions(如reactive、ref和computed)的用法、特点和相互关系。此外,还涵盖了生命周期函数、父子组件通信和pinia状态管理库的应用。
摘要由CSDN通过智能技术生成

1.setup

<script>
export default {
  setup () {
    console.log('setup',this)
    const message = 'this is message'
    const logMessage = () => {
      console.log(message)
    }
    return{
      message,
      logMessage
    }
  }
}
</script>

<template>
  <div>
    {{ message }}
    <button @click="logMessage">log</button>
  </div>
</template>

上面是script原始复杂写法

下面是

<script setup>
const message = 'this is message'
const logMessage = () => {
  console.log(message)
}
</script>

问题:

1.setup选项执行的时机

beforeCreate钩子之前,自动执行

2.setup写代码的特点

定义数据+函数,以对象的方式return

3.

经过语法糖的封装更简单的使用组合式API

4.setup中this还执行组件实例码

指向undefined

2.reactive() ref()

reactive():接受对象类型数据的参数传入并返回一个响应式对象

ref():接受简单类型或者对象类型数据的参数传入并返回一个响应式对象

<script setup>
import { reactive } from 'vue'
//响应式对象:会引起视图的更新
const state = reactive({
  count:0
})
const setCount = () => {
  state.count++
}
</script>
<template>
  <div>
    <button @click="setCount">{{ state.count }}</button>
  </div>
</template>
<script setup>
import { ref } from 'vue'
//响应式对象:对引起视图的更新
const count = ref(0)
const setCount = () => {
  //脚本区域修改ref的额响应式对象数据,必须通过.value属性
  count.value++
}
</script>
<template>
  <div>
    <button @click="setCount">{{ count }}</button>
  </div>
</template>

步骤:

1.从vue包中导入reactive函数(ref函数)

2.在

问题

1.reactive和ref函数的共同作用?

用函数调用的方式产生响应式数据

2.reactive vs ref

1.reactive不能处理简单类型的数据

2.ref参数类型支持更好,但必须通过.value修改访问

3.ref函数依赖于reactive函数

3.实际中推荐?

推荐ref,更加灵活

computed计算属性函数

<script setup>
import { ref } from 'vue'
import { computed } from 'vue'
const list = ref([1,2,3,4,5,6,7,8])
//filter筛选数据
const computedList = computed(() => {
  return list.value.filter(item => item > 2)
})
//定时器,3秒后执行 push加入数据
setTimeout(() => {
  list.value.push(9,10)
},3000)
</script>
<template>
  <div>
    原始数据:{{  list }}
  </div>
  <div>
    计算数据:{{ computedList }}
  </div>
</template>

步骤:

1.导入computed函数

2.执行函数在回调参数中return基于响应式数据做计算的值,用变量接收

注意事项

1.计算属性中不应该有“副作用” (用watch)

比如异步请求、修改dom

2.避免直接修改计算属性的值

计算属性应该是只读的

watch函数

作用:侦听一个或多个数据的变化,变化时执行回调函数

参数:1.immediate(立即执行)2.deep(深度侦听)

<!--侦听单个数据-->
<script setup>
import { ref,watch } from 'vue'
const count = ref(0)
const setCount = () => {
  count.value++
}
watch(count,(newVal,oldVal)=>{
  console.log('count变化了',newVal,oldVal)
})
</script>
<template>
  <div>
    <button @click="setCount">+{{ count }} </button>
  </div>
</template>
<!--侦听多个数据,无论谁变化,都执行回调函数-->
<script setup>
import { ref,watch } from 'vue'
const count = ref(0)
const setCount = () => {
  count.value++
}
const name = ref('cp')
const setName = () => {
  name.value = 'pc'
}
watch([count,name],([newCount,newName],[oldCount,oldName]) => {
  console.log('count/name变化了',[newCount,newName],[oldCount,oldName])
})
</script>
<template>
  <div>
    <button @click="setCount">+{{ count }} </button>
    <button @click="setName">+{{ name }} </button>
  </div>
</template>
<!--immediate,在创建时就执行一次回调函数-->
<script setup>
import { ref,watch } from 'vue'
const count = ref(0)
const setCount = () => {
  count.value++
}
watch(count,() => {
  console.log('count变化了')
},{
  immediate:true
})
</script>
<template>
  <div>
    <button @click="setCount">+{{ count }} </button>
  </div>
</template>
<!--deep,默认是浅层监听,该例子若没有deep:true就不会执行watch-->
<!--把ref换成reactive也可以执行watch,因为reactive默认开启了deep-->
<script setup>
import { ref,watch } from 'vue'
const state = ref({count:0})
const setCount = () => {
  state.value.count++
}
watch(state,() => {
  console.log('count变化了')
},{
  deep:true
})
</script>
<template>
  <div>
    <button @click="setCount">+{{ state.count }} </button>
  </div>
</template>
<!--在不开启deep的情况下,精确侦听对象的某个属性-->
<script setup>
import { ref,watch } from 'vue'
const state = ref({
  name:'maying',
  age:18
})
const changeName = () => {
  state.value.name = 'maying-student'
}
const changeAge = () => {
  state.value.age = 20
}
watch(
  ()=> state.value.age,
  ()=> {
    console.log('age变化了')
  }
)
//deep性能损耗,尽量不开启deep
</script>
<template>
  <div>
    <button @click="changeName">{{ state.name }} </button>
    <button @click="changeAge">{{ state.age }} </button>
  </div>
</template>

步骤:

1.导入watch函数

2.执行watch函数传入要侦听的响应式数据(ref对象)和回调函数

问题

1.watch的第一个参数,ref对象需要添加.value吗

不需要,watch会自动读取

2.watch只能侦听单个数据吗

单个或多个

3.不开启deep,直接修改嵌套属性能触发回调?

不能,默认是浅层侦听

4.不开启deep,侦听层次比较深的属性?

把一个参数写成函数的写法,返回要监听的具体属性(精确侦听)

生命周期函数 (组合式API)

选项式API组合式API
beforeCreate / createdsetup创建
beforeMountonBeforeMount挂载
mountedonMounted
beforeUpdateonBeforeUpdate更新
updatedonUpdated
beforeUnmountonBeforeUnmount卸载
unmountedonUnmounted
<!--生命周期函数可以执行多次,在时机成熟时依次执行-->
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
  console.log('组件挂载完毕mounted执行了1')
})
onMounted(() => {
  console.log('组件挂载完毕mounted执行了2')
})
</script>
<template>
  <div>
  </div>
</template>

步骤:

1.导入生命周期函数

2.执行生命周期函数,传入回调

问题

1.组合式API中生命周期函数的格式

on+生命周期名字

2.组合式API可以用onCreated吗

不能,应该是setup中

3.组合式API中组件卸载完毕执行哪个?

onUnmounted

父子通信(组合式API)

父传子

基本思想:

1.父组件中给子组件绑定属性

2.子组件内部通过props选项接收

<!--父组件-->
<script setup>
//setup语法糖下,局部组件无需注册就可以用
import SonCom from './son.vue'
import { ref } from 'vue';
//响应式数据
const count = ref(100)
setTimeout(()=>{
  count.value = 200
},3000)
</script>
<template>
  <div class="father">
    <h3>父组件App</h3>
    <SonCom :count="count" message="father message"/>
</div>
</template>
<!--子组件-->
<script setup>
//通过 defineProps “编译器宏” 接收
const props = defineProps({
    message: String,
    count: Number
})
console.log(props)
</script>
<template>
<div class="son">
    <h3>子组件Son</h3>
    <div>
        父组件传入的数据:{{ message }}-{{ count }}
    </div>
</div>
</template>
<style>
</style>

子传父

基本思想:

1.父组件中给子组件标签通过@绑定事件

2.子组件内部通过$emit方法触发事件

<!--父组件-->
<script setup>
//setup语法糖下,局部组件无需注册就可以用
import SonCom from './son.vue'
const getMessage = (msg) => {
  console.log(msg)
}
</script>
<template>
  <div class="father">
    <h3>父组件App</h3>
    <SonCom @get-message="getMessage"/>
</div>
</template>
<!--子组件-->
<script setup>
const emit = defineEmits(['get-message'])
const sendMsg = () => {
    emit('get-message','this is son message')
}
</script>
<template>
<div class="son">
    <h3>子组件Son</h3>
    <button @click="sendMsg">触发事件</button>
</div>
</template>
<style>
</style>

问题

1.父传子用什么接收props

defineProps({属性名:类型})

2.setup中怎么使用父组件传来的数据

const props = defineProps({属性名:类型})

3.子传父用什么得到emit方法

defineEmits([‘事件名称’])

模板引用 defineExpose()

获取真实的dom对象或者组件实例对象

<!--父组件-->
<script setup>
import { onMounted,ref } from 'vue';
import SonCom from './son.vue'
const h1Ref = ref(null)
const comRef = ref(null)
//组件挂载完毕后才能获取
onMounted(() => {
  console.log(h1Ref.value)
  console.log(comRef.value)
})
</script>
<template>
<h1 ref="h1Ref">这是dom标签h1</h1>
<SonCom ref="comRef"/>
</template>
<!--子组件-->
<script setup>
import { ref } from 'vue'
const name = ref('test name')
const setName = () => {
    name.value = 'test new name'
}
defineExpose({
    name,setName
})
</script>
<template>
<div class="son">
    <h3>子组件Son</h3>
    
</div>
</template>

结果:
在这里插入图片描述

defineExpose 编译宏方法

默认情况下,

问题

1.获取模板引用的时机

组件挂载完毕

2.defineExpose编译宏的作用

显示暴露组件内部的属性和方法

provide和inject(跨层组件通信)

作用与场景:顶层组件向任意底层组件传递数据和方法,实现跨层组件通信

传递普通数据

1.顶层组件通过provide提供数据

2.底层组件通过inject获取数据

<!--顶层组件-->
provide('data-key','this is room data')
<!--底层组件-->
const roomData = inject('data-key')

传递响应式数据

<!--顶层组件-->
const count = ref(0)
provide('count-key',count)
<!--底层组件-->
const countData = inject('count-key')

跨层传递方法

<!--顶层组件-->
const count = ref(0)
const setCount = () => {
	count.value++
}
provide('setCount-key',setCount)
<!--底层组件-->
const setCount = inject('setCount-key')
<button @click="setCount">修改顶层组件数据coount</button>

问题

1.provide和inject作用

跨层组件通信

2,在传递中怎么保持响应式

第二个参数传递ref对象

3.底层组件想通知顶层组件做修改,怎么做(底层向顶层传)

传递方法,底层组件调用方法

4.只有一个顶层组件或底层组件吗

相对概念,存在多个关系

pinia

符合直觉的 Vue.js 状态管理库

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。

可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})

Setup Store 中:

  • ref() 就是 state 属性
  • computed() 就是 getters
  • function() 就是 actions
<script setup>
import { useCounterStore } from '@/stores/counter'
// 可以在组件中的任意位置访问 `store` 变量 ✨
const store = useCounterStore()
</script>

为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:

storeToRefs保持数据的响应式解构

<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
//const { name, doubleCount } = store 响应式丢失
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>

r’
// 可以在组件中的任意位置访问 store 变量 ✨
const store = useCounterStore()


为了从 store 中提取属性时保持其响应性,你需要使用 `storeToRefs()`。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:

storeToRefs保持数据的响应式解构

```vue
<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
//const { name, doubleCount } = store 响应式丢失
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>
  • 43
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值