欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > VUE3.0基础入门笔记

VUE3.0基础入门笔记

2025/2/24 13:29:47 来源:https://blog.csdn.net/qq_43787947/article/details/143016978  浏览:    关键词:VUE3.0基础入门笔记

一、响应式基础

1.ref():声明基本类型,引用类型,函数需接收参数,并将其包裹在一个带有 .value 属性的对象中,在模板中使用 ref 时,我们不需要附加 .value,当在模板中使用时,ref 会自动解包。

<template><button @click="count++">{{ count }}</button>
</template><script setUp>import { ref } from 'vue'    const count = ref(0)console.log(count.value)
</script>

2.reactive():声明对象、数组等复杂类型。

<template><button @click="state.count++">{{ state.count }}</button>
</tempalte>
<script setUp>import { reactive } from 'vue'const state = reactive({ count: 0 })console.log(state)
</script>

3. toRefs与toRef深度剖析

3.1 toRefs()函数用于将一个响应式对象的所有属性转换为单独的响应式引用。这个函数通常与解构赋值一起使用,以便我们可以轻松地访问响应式对象的每个属性。

<script setUp> 
import { reactive, toRefs  } from 'vue'
const state = reactive({name: 'Commas',age: 18
})
//现在解构这个对象,并保持每个属性的响应式,这时toRefs 就派上用场了
//这样,name 和 age 就成为了单独的响应式引用,我们可以直接使用它们,而不必担心失去响应式。
const { name, age } = toRefs(state);
</script> 

3.2 toRef()函数用于为源响应式对象的某个属性创建一个响应式引用。与 toRefs 不同的是,toRef 只能用于单个属性。

<script setUp>
//假设我们有一个响应式对象 state,包含name和age两个属性,现在我们只想为name属性创建一个响应式引用
//这样name就成为了state.name的响应式引用,我们可以直接修改name.value,这个修改会反映state.nam上。const name = toRef(state, 'name');
</script>

3.3 联系与区别

(1)toRefs 和 toRef 都用于创建响应式引用。

(2)toRefs 用于将整个响应式对象的所有属性转换为响应式引用,而 toRef 只用于单个属性。

(3)toRefs 通常与解构赋值一起使用,方便同时访问多个属性,而 toRef 用于为单个属性创建响应式引用。

二、计算属性 computed()

getter与setter的计算属性

 get()获取数据

 set()改变数据

<template><div class="computed">姓: <input type="text" v-model="firstName" /> <br />名: <input type="text" v-model="lastName" /><br />姓名: <span>{{ fullName }}</span><br /><button @click="changeName">更改姓名</button>
</template><script setUp>
import { computed, reactive } from "vue";
let firstName = ref("han");
let lastName = ref("召华");
//默认是 getter 方法
const fullName = computed(() => {return firstName.value + "_" + lastName.value;
});//有getter与setter的计算属性
let fullName = computed({get() {return (firstName.value.slice(0, 1).toUpperCase() +firstName.value.slice(1) +"-" +lastName.value);},set(val) {let [str1, str2] = val.split("-");firstName.value = str1;lastName.value = str2;},
});
function changeName() {fullName.value = "huang-aaa";
}
</script>

三、watch与watchEffect

3.1watch 监听函数

 情况一:ref(监听不需要加.value)

 情况二:reactive(默认深度监听且deep不可变)

 情况三:getter函数监听 响应式对象的某个属性且是基本数据类型

 情况四:监视多个数据使用数组情况 [() => obj.value.a.b,() => obj.value.a]

<template><h2>one:{{ one }} | two: {{ two.value }}</h2><button @click="one++">改变 one 数据</button><button @click="two.value++">改变 two 数据</button>
</template><script setup>import { watch, ref ,reactive} from 'vue'// 变量1const one = ref(0)// 变量2const two = reactive({value: 10})// 监听多个变量// 第一个参数变为数组形式,每个下标对应一个要监听的变量// 第二个参数的函数传参改为每项数组形式,每个数组对应新旧值的参数watch([one, () => two.value], ([oneNew, twoNew], [oneOld, twoOld]) => {console.log(`one: ${oneNew}(新) ——— ${oneOld}(旧)`);console.log(`two: ${twoNew}(新) ——— ${twoOld}(旧)`);});
</script>

3.2 watchEffect 监听函数

 1.立即运行一个函数,同时响应式追踪其依赖,并在依赖更改时重新执行该函数

 2.watch与watchEffect区别

    2.1都能监听响应式数据变化,只不过见监听方式不同

    2.2watch:要明确指出监视数据

    2.3watchEffect:不用指出监视数据(函数使用哪些,就监视哪些属性)

<script setUp>
let obj = ref({a: {b: {watchName: "韩召华",watchAge: 28,},},
});watchEffect(() => {if (obj.value.a.b.watchAge > 23) {console.log("watchEffect--------", "监听到了");}});
</script>

四、ref获取DOM的使用

  1.用于修改HTML的DOM

  2.作用在组件上时,获取的是组件实例对象,子组件需通过defineExpose暴露数据,父组件才能使用

const presonDom = ref();
console.log("DOM实例", presonDom);

五、props使用

子组件接收

 1.defineProps 接收list + 限制类型

    defineProps(['a','b'])接收

    defineProps带默认值写法

 const props = defineProps({name: String,age:{type: Number,default: 23}})

 ts写法defineProp<{list?:Persons}>()

 2.withDefaults 接收list + 限制类型 + 限制必要性 + 指定默认值

 withDefaults(defineProps<{list?:Persons}>(),{list:()=>[{id:0,name:"张三",age:18}]})

六、生命周期

 1.创建 setUP

 2.挂载前 onBeforeMount(()=>{})

 3.挂载后 onMounted(()=>{ console.log(子组件挂载优先于父组件) })

 4.更新前 onBeforeUpdate(()=>{})

 5.更新后 onUpdate(()=>{})

 6.卸载前 onBeforeUnmount(()=>{})

 7.卸载后 onUnmounted(()=>{})

七、hooks

 1.use命名

 2.return 可用对象,数组,方法暴露数据且包含属性和方法

3.使用如下

八、routes路由

1.RouterLink 跳转路由

    >to的使用对象:name,path

    >active-class 激活样式

 2.RouterView 展示路由

 3.params query props 路由传参

 4.push推入,replace 替换(无路由记录,直接作用于RouterLink上)

 5.编程式导航 useRouter

 6.redirect 重定向

const router = useRouter();
router.push();
router.replace();

九、集中式状态数据管理 redux | vuex | pinia

1.npm i pinia

2.创建pinia(创建store文件-根据页面组件命名-用use命名store文件-defineStore定义store - 在使用组件引入该store文件 - 通过talkStore.value或者talkStore.$store.value)

3.pinia 修改的三种方式

  3.1第一种方式修改 countstore.sum 直接修改值

  3.2第二种方式修改 批量

 countstore.$patch ({sum: 100,xxx: 123})

  3.3第三种方式 使用actions

 //直接调用actions里的方法

  countStore.increment('参数集');

 4.storeToRefs响应式数据 只关注store中数据,不会对方法进行ref包裹

 5.getters 计算属性

 6.$subscribe 订阅 监听store中的数据变化

 countStore.$subscribe((mutate,satat)=>{console.log('监听',mutate,satat)}

 十、组件通信

 1.props

  父传子":data"

 子传父 子defineProps(['sentData']) 通过事件传参

 在父组件:sentData="getData"

 getData( value ) {console.log('接收子传数据',value);}

 2.自定义 defineEmits

  子组件 const emit = defineEmits(['eimtData'])

 emit('emitData',{name:'张三',age:18})

  父组件 @emitData="getData"

   getData( value ) {console.log('接收子传数据',value);}

  3._mitt工具-总线

 npm引入 mitt

 const emitter =mitt()

 emitter.emit() // 触发钩子

 emitter.on()   // 监听钩子

 emitter.off()  // 解绑钩子(一般在onUnmounted()里使用)

 emitter.all()  // 清空事件

 4.v-model方式

 5.$attrs 祖孙组件传值

  如下图所示,A 和 B、B 和 C/D 都是父子关系,C 和 D 是兄弟关系,A 和 C/D 是隔代关系。

$attrs: 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (包含class 和 style)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (包含class 和 style ),并且可以通过 v-bind=“$attrs” 传入内部组件。在Vue3.0版本中,$listeners / inheritAttrs已被移除掉,现在事件监听器是 $attrs 的一部分。

案例组件(父子孙)

同样,我们创建3个组件: 父组件:parent.vue,子组件:child.vue,孙组件:grandchild.vue

  • 父组件:parent.vue
<template><div class="parent-root"><childclass="child":name="name":age="age"@grandchildByValue="grandchildByValue"></child></div>
</template><script>
import { ref } from 'vue'
import child from '@/views/test/child.vue'
export default {name: 'parent',components: { child },props: {},setup() {const name = ref('小明'),age = ref(18),grandchildByValue = value => {console.log('孙组件传过来的值:', value)}return {name,age,grandchildByValue}}
}
</script><style scoped lang="scss"></style>
  • 子组件:child.vue
<template><div class="child-root"><grandchild v-bind="$attrs"></grandchild></div>
</template><script>
import { ref } from 'vue'
import grandchild from '@/views/test/grandchild.vue'
export default {name: 'child',components: { grandchild },props: {},setup(context) {console.log('attrs:', context.attrs) }
}
</script><style scoped lang="scss"></style>
  • 孙组件:grandchild.vue
<template><div class="grandchild-root"><p>name:{{ name }}</p><p>age:{{ age }}</p><el-button type="primary" @click="fn">孙子传值爷爷</el-button></div>
</template><script>
export default {name: 'grandchild',components: {},props: {name: {type: String,default: ''},age: {type: Number,default: null}},setup(context) {const fn = () => {context.emit('grandchildByValue', '爷爷,您好')}return {fn}}
}
</script><style scoped lang="scss"></style>

6.$refs跟$parent

ref 需要结合defineExpose暴露数据使用

1、$refs用法

父组件(模板代码:参数$refs
 

<button @click="getAllChild($refs)">让所有孩子的书变多</button>
<Child1 ref="c1"/>
<Child2 ref="c2"/>

 按钮对应的函数代码
这里,就可以同时获取到c1和c2两个实例

	function getAllChild(refs:{[key:string]:any}){console.log(refs)for (let key in refs){refs[key].book += 3}}

两个子组件
暴露变量,这样父组件就可以操作该变量

// 把数据交给外部
defineExpose({book})

2、$parent用法

子组件(模板代码:参数$parent

<button @click="minusHouse($parent)">干掉父亲的一套房产</button>

按钮对应的函数代码

	function minusHouse(parent:any){parent.house -= 1}

 父组件(暴露变量

	// 向外部提供数据defineExpose({house})

  7.provide_inject依赖注入 祖孙之间直接通信

我们可以使用provide和inject使顶层组件向底层组件提供数据和方法。

Provide

语法格式: provide('key',顶层组件中的数据或方法)

顶层组件示例代码如下:

<template>顶层组件<Middle />
</template><script setup>
import { provide, ref } from 'vue'
import Middle from './components/middle.vue'
const count = ref('这是顶层组件提供的数据')
provide('count-key', count)		// 向底层组件提供数据
const sayHello = () => {console.log('你好,我是顶层组件提供的方法')
}
provide('sayHello', sayHello)   // 向底层组件提供方法
</script>

 中间组件示例代码如下:

<template>中间组件<Bottom />
</template><script setup>
import Bottom from './bottom.vue'
</script>

inject

底层组件通过inject函数获取数据并通过变量接收,其语法格式如下:

const 变量名=inject('key')

底层组件示例代码如下: 

<template>底层组件<button @click="sayHello">sayHello</button><div>来自顶层组件的数据:{{ countData }}</div>
</template><script setup>
import { inject } from 'vue'
const sayHello = inject('sayHello')
const countData = inject('count-key')
</script>

十一、shallowReactive和shallowRef

shallowReactive

(1)作用:与reactive作用类似,但只处理对象最外层属性的响应式(浅响应式)

(2)使用场景:如果有一个对象数据,结构比较深(内嵌多层对象),但只需要最外层的属性进行响应式,则使用shallowReactive

shallowRef

(1)作用:与ref作用类型,但只处理基本数据类型的响应式,不处理对象类的响应式

(2)使用场景:如果有一个对象数据,后续功能不会修改该对象中的属性,而是生成新的对象来替换,则使用shallowRef

十二、readonly和shallowReadonly

(1)readonly:将包裹的对象变为只读,并且是深度只读
(2)shallowReadonly:浅层属性为只读,深层次属性可以修改

十三、toRaw和markRaw

     toRaw将代理对象变成普通对象,数据发生变化,不会更新
     markRaw标记的对象数据,从此以后再也不能成为代理对象了

两者区别:toRaw会将整个对象变成非响应式的,markRaw可以指定哪些属性值可以变化

<template><div><h2>toRaw与markRaw</h2><h3>state:{{state}}</h3><button @click="updateToRaw">测试toRaw</button><button @click="updateMarkRaw">测试markRaw</button></div>
</template><script lang="ts">
import { computed, defineComponent,reactive,ref,toRaw,markRaw } from 'vue'
interface UserInfo {name:string,age:number,likes?:string[]
}
// 引入子集组件
import Child from './components/child.vue';
export default defineComponent({components:{Child},setup(){const state = reactive<UserInfo>({name:'小明',age:12,})const updateToRaw = () => {const user = toRaw(state)user.name += '-----'console.log('测试')}const updateMarkRaw = () => {// state.likes = ['吃','喝']// state.likes[0] += '-----'const likes = ['吃','喝']state.likes = markRaw(likes)setInterval(() => {console.log('定时器走起来')if (state.likes) {state.likes[0] += '----'}},1000)console.log('测试')}return {updateToRaw,updateMarkRaw,state}}
})
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}nav {padding: 30px;
}nav a {font-weight: bold;color: #2c3e50;
}nav a.router-link-exact-active {color: #42b983;
}
</style>

十四、自定义customRef

(1)customRef 用于自定义返回一个ref对象,可以显式地控制依赖追踪和触发响应,接受工厂函数
(2)两个参数分别是用于追踪的 track 与用于触发响应的 trigger,并返回一个一个带有 get 和 set 属性的对象使用:import {customRef} from 'vue';function useDebouncedRef(value) {return customRef((track, trigger) => {return {get() {track()	追踪当前数据return value},set(newValue) {value=newValuetrigger() 触发响应,即更新界面},}})}通过customRef返回的ref对象,和正常ref对象一样,通过x.value修改或读取值类型声明:function customRef<T>(factory: CustomRefFactory<T>): Ref<T>type CustomRefFactory<T> = (track: () => void,trigger: () => void) => {get: () => Tset: (value: T) => void}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词