一、安装前提
node需要16.0版本以上,如何升级node参考[mac升级node](https://blog.csdn.net/weixin_43676252/article/details/128578911)
二、创建vue3项目
npm init vue@latest
三、setup
<script>
// vue2写法
export default {setup() { console.log('setup')let count = 1const addcount = () => { console.log(count);}return {count,addcount}},beforeCreate() { console.log('beforeCreate')}
}
</script>
<template><button @click="addcount">+{{ count }}</button>
</template>
注意:setup比beforeCreate先执行,setup中生命的变量和函数,一定要return出去,才能在dom中使用和调用,如果变量和函数太多的话,这种方式显然不方便,所以,vue3中有了setup语法糖的用法,用法如下:
<script setup>//vue3写法let count = 1const addcount = () => { console.log(count);}
</script>
<template><button @click="addcount">+{{ count }}</button>
</template>
四、reactive和ref
共同点:用函数调用的方式生成响应式数据
区别:
- reactive的参数只能是对象类型
- ref可以是对象类型,也可以是简单类型
- ref在脚本区域必须通过.value访问修改
- ref内部实现依赖于reactive
用法:推荐使用ref
<script setup>
// reactive
import { reactive } from "vue";
const param = reactive({ count: 0 });
const addcount = () => {console.log(param);param.count++
};
// ref
import { ref } from 'vue'
const refCount = ref(0)
const addrefCount = () => { refCount.value++
}
</script>
<template><!-- reactive --><button @click="addcount">+{{ param.count }}</button><!-- ref --><button @click="addrefCount">+{{ refCount }}</button>
</template>
五、computed计算属性函数
需注意:
- 计算属性函数中,只负责计算数值,不应该有异步请求或者修改dom之类的操作,这些操作可以放在watch中实现
- 避免直接修改计算属性的值,例子中的newArr
用法:
<script setup>
import { ref,computed } from 'vue'
const refArr= ref([1,2,3,4,5,6])
const newArr = computed(() => { return refArr.value.filter(item=>item>2)
})
</script>
<template><div>{{ refArr }}</div> //[ 1, 2, 3, 4, 5, 6 ]<div>{{ newArr }}</div>//[ 3, 4, 5, 6 ]
</template>
如果改变refArr的值
<script setup>
import { ref,computed } from 'vue'
const refArr= ref([1,2,3,4,5,6])
const newArr = computed(() => { return refArr.value.filter(item=>item>2)
})
setTimeout(() => {refArr.value.push(7,8)
}, 3000);
</script>
<template><div>{{ refArr }}</div> //一开始是[ 1, 2, 3, 4, 5, 6 ],三秒之后是[ 1, 2, 3, 4, 5, 6, 7, 8 ]<div>{{ newArr }}</div>//一开始是[ 3, 4, 5, 6 ],三秒之后是[ 3, 4, 5, 6, 7, 8 ]
</template>
六、watch函数
<script setup>
import { ref, watch } from 'vue'const count = ref(0)
const age = ref(18)
const addCount = () => { count.value++
}
const addAge = () => { age.value++
}// 监听一个变量
watch(count, (newCount,oldCount) =>{
console.log(count.value,newCount,oldCount); //1 1 0
})// 监听多个变量
watch([count, age], ([newCount, newAge], [oldCount, oldAge]) => {
console.log(count.value,newCount,oldCount); //1 1 0
console.log(age.value,newAge,oldAge); //1 1 0
})// immediate和deep用法
// watch(count, (newCount,oldCount) =>{
// console.log(count.value,newCount,oldCount); //1 1 0
// }, {immediate:true,deep:true})// watch监听的ref对象默认是浅层监听,直接修改嵌套的对象属性不会触发回掉
const state = ref({ age: 10 })
const addstate = () => { state.value.age++
}
watch(state, () => { console.log(state) //不会打印
})
watch(state, () => { console.log(state.value.age) //开启deep,会打印
}, { deep: true })// 只监听对象中的某个字段
const json = ref({ name: '章三', age: 18 })
const addJsonAge = () => { json.value.age++
}
watch(() => json.value.age, (newAge,oldAge) => {
console.log(json.value.age,newAge,oldAge);
})
</script>
<template><button @click="addCount">++{{ count }}</button><button @click="addAge">++{{ age }}</button><button @click="addstate">++{{ state.age }}</button><button @click="addJsonAge">++{{ json.age }}</button>
</template>
七、生命周期API
| 选项式API | 组合式API |
|---|---|
| beforeCreate/created | setup |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeUnmount | onBeforeUnmount |
| unmounted | onUnmounted |
八、父子传值
父传子
<script setup>
import { ref } from 'vue'
import son from '@/views/son.vue'
const count = ref(200)
</script><template><h2>父组件</h2><son :count="count"/>
</template><style scoped>
</style>
<script setup>
const props = defineProps({count:Number
})
console.log(props.count);
</script><template><div>子组件</div><div>父组件传过来的值{{ count }}</div>
</template><style scoped>
</style>
子传父
<script setup>
import { ref } from 'vue'
import son from '@/views/son.vue'
const count = ref()
const getCount = (param) => { count.value = param
}
</script><template><h2>父组件</h2><div>子组件传过来的{{ count }}</div><son @get-count="getCount"/>
</template><style scoped>
</style>
<script setup>
// defineEmits(['事件名称','事件名称'])
const emit = defineEmits(['get-count'])
const sendCount = () => { console.log(1);emit('get-count',300)
}
</script><template><div>子组件</div><button @click="sendCount">点我</button>
</template><style scoped>
</style>
九、模版引用
vue2:
this.$refs.form.submit()
vue3:访问当前组件的dom
<script setup>
import { ref,onMounted } from 'vue'
import son from '@/views/son.vue'
// 第一步 通过ref生成ref对象
const parentRef = ref(null)// 第三步,挂载之后才可以调用到
onMounted(() => {console.log(parentRef.value);
})</script><template><!-- 第二步 通过ref标识绑定ref对象 --><div ref="parentRef">父组件</div><son />
</template><style scoped>
</style>
vue3访问子组件的属性和方法
<script setup>
import { ref,onMounted } from 'vue'
import son from '@/views/son.vue'
// 第一步 通过ref生成ref对象
const sonRef = ref(null)// 第三步,挂载之后才可以调用到
onMounted(() => {sonRef.value.setName()console.log(sonRef.value.name);
})</script><template><!-- 第二步 通过ref标识绑定ref对象 --><div >父组件</div><son ref="sonRef" />
</template><style scoped>
</style>
<script setup>
import { ref } from 'vue'
const name = ref('test name')
const setName = () => { name.value = 'test new name'
}
// 默认情况下<script setup>语法糖下组件内部的属性和方法是不开发给父组件的,
// 可以通过defineExpose编译宏知道哪些属性和方法允许访问
defineExpose({name,setName
})
</script><template><div>子组件</div>
</template><style scoped>
</style>