前言:以官方文档为蓝本的Vue学习过程中,需要的一些细节以及实际开发中遇到的总结点。
Vue的学习过程中,主要分几个大块:
- 基础知识:框架自行的一些语法(官网里面的基础)
- 组件相关:尤其是组件之间的各类通信方式,在写/抽离组件里面经常用到,单独一篇文章总结。
官方文档:
- Vue 2.x:https://cn.vuejs.org/v2/guide/
Vue 3:https://v3.cn.vuejs.org/guide/introduction.html
计算属性+方法+侦听器
计算属性(computed)和方法(methods)的区别
计算属性是基于他们的依赖来进行缓存的
“他们的依赖”指的是data数据域中的data数据,如果其变动,计算属性值才会变
文档:https://cn.vuejs.org/v2/api/#watch
侦听器(watch)的一些注意事项
实际开发过程中:
- 非的确必要,尽量不要使用watch监听,实际过程中,会造成许多问题,比如渲染顺序等,会给后续添加功能带来难以维护的问题
- 当监听的数据不是一个简单的基本类型,比如一个对象,一个数组,此时应该使用深度监听:deep:true;当想让监听器一启动就触发一次watch,应该使用: immediate: true。
直接
watch
监听对象内的是检测不到变化的,因为对象的指向并没有发生改变。Vue中的watch监听对象内属性的变动方案
使用deep属性
new Vue({
data: {
count: 10,
blog:{
title:'my-blog',
categories:[]
}
},
watch: {
blog:{
handler(newVal,oldVal){
console.log(`new: ${newVal}, old: ${oldVal}`);
},
deep:true
}
}
})
里面的deep
设为了true
,这样的话,如果修改了这个blog
中的任何一个属性,都会执行handler
这个方法。不过这样会造成更多的性能开销,尤其是对象里面属性过多,结构嵌套过深的时候。而且有时候我们就只想关心这个对象中的某个特定属性,这个时候可以这样
用字符串来表示对象的属性调用
new Vue({
data: {
count: 10,
blog:{
title:'my-blog',
categories:[]
}
},
watch: {
'blog.categories'(newVal, oldVal) {
console.log(`new:${newVal}, old:${oldVal}`);
},
}
})
使用计算属性(computed)
new Vue({
data: {
count: 10,
blog:{
title:'my-blog',
categories:[]
}
},
computed: {
categories() {
return this.blog.categories;
}
},
watch: {
categories(newVal, oldVal) {
console.log(`new:${newVal}, old:${oldVal}`);
},
},
})
参考:https://segmentfault.com/a/1190000018080301
生命周期实践理解
vue2当中:
- beforeCreate:在实例初始化之后,数据观测和事件配置之前被调用
- created:在实例创建完成后被立即调用
- beforeMount:在挂载开始之前被调用
- mounted:el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子
- beforeUpdate:数据更新时调用,发生在虚拟DOM打补丁之前
- updated:由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子
- beforeDestroy:实例销毁之前调用
- destroyed:实例销毁后调用
<script>
setup() {
console.log('----setup第一个执行----')
// vue3.x生命周期写在setup中
onBeforeMount(() => {
console.log('------vue3中onBeforeMount-----')
})
onMounted(() => {
console.log('------vue3中onMounted-----')
})
onRenderTriggered((event) => {
console.log('------vue3中onRenderTriggered-----', event)
})
},
// vue2当中的
beforeCreate() {
console.log('----vue2中beforeCreate第二个执行----')
},
// vue2当中的
created() {
console.log('----vue2中created第三个执行----')
},
</script>
Vue3.x相交Vue2.x的API差异
- 参考教程:Vue3.0 新特性以及使用经验总结
组合式API
defineComponent({})
服务于typescript项目,defineComponent 本身的功能很简单,但是最主要的功能是为了 ts 下的类型推导。对于一个 ts 文件,如果我们直接写
对于编辑器而言,{} 只是一个 Object 的类型,无法有针对性的提示我们对于 vue 组件来说 {} 里应该有哪些属性。但是增加一层 defineComponet 的话,export default {}
这时,{} 就变成了 defineComponent 的参数,那么对参数类型的提示,就可以实现对 {} 中属性的提示,外还可以进行对参数的一些类型推导等操作。export default defineComponent({})
setup()
<script> setup() { console.log('----setup第一个执行----') // vue3.x生命周期写在setup中 onBeforeMount(() => { console.log('------vue3中onBeforeMount-----') }) onMounted(() => { console.log('------vue3中onMounted-----') }) // 调试哪些数据发生了变化 onRenderTriggered((event) => { console.log('------vue3中onRenderTriggered-----', event) }) // ref则处理 js 基础类型的双向绑定,也能处理对象 const year = ref(0) // reactive用于处理对象的双向绑定 const user = reactive({nickname: 'xiaofan', age: 26, gender: '女'}) const timer = setInterval(() => { year.value++ user.age++ if (year.value === 2) { clearInterval(timer) } }, 1000) // 侦听 reactive 定义的数据 watch( () => user.age, (curAge, preAge) => { console.log('reactive新值:', curAge, 'reactive老值:', preAge) } ) // 侦听 ref 定义的数据 watch(year, (newVal, oldVal) => { console.log('ref新值:', newVal, 'ref老值:', oldVal) }) // 也可以使用 toRefs 实现导出时候进行对象结构 return { year, user, blockContent: `AntV 是蚂蚁。`, } }, </script>
watch
```vue<a name="vTO6p"></a> ## vue3路由相关 - [vue3.0 router路由跳转传参(router.push)](https://blog.csdn.net/animatecat/article/details/117257037) - [【Vue】015. Vue-Router(三)—— 路由传参](https://juejin.cn/post/6962528855513006117) - 官网:[https://router.vuejs.org/zh/](https://router.vuejs.org/zh/) <a name="AOnGe"></a> ### 得到动态路由信息 - [x] 在`index.ts`中得不到该路由页面的相关信息~~===选一个比较好一点的传值方案,最好在路由index.ts 设置(props)。~~在路由使用组件中就可以使用。 参考:[https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html) ```vue <script lang="ts"> import {useRouter} from 'vue-router' export default defineComponent({ setup() { // 获取当前路由 const router = useRouter() // 路由信息 const router_info = router.currentRoute.value const lookRouter = () => { console.log(router_info) } return { router_info, lookRouter, } }, }) </script>
定义数据
Vue3定义普通数据
- 【不建议】:也还可以使用Vue2中的data,但是不能在setup()中使用this访问
不再用vue2当中的data API了(因为不能进行操作,功能性大大减少)
- 【建议】:使用ts的接口类型定义数据
```vue
<a name="u5iUn"></a> ### Vue3定义响应数据 <a name="Mp2Px"></a> #### ref ```typescript <a-modal v-model:visible="visible" :title="updateItem === 'delete_user' ? '删除账户' : '修改信息'" @ok="handleOkInfo" @cancel="handleCancelInfo" ok-text="确认" cancel-text="取消" > // ----------------------------------------------------------------------- import {ref} from 'vue' const visible = ref<boolean>(false) const handleOkInfo = (e: MouseEvent) => { visible.value = false } return { visible, }
reactive
这个更过使用在对象和数组类型的响应式定义数据,因为在vue2中,对于数组和对象是不能够响应式的需要监听,而在vue3中,以此作为优化来定义响应式数据。
Vue2中的data
如何在setup中使用data中的数据库?
按照以前vue2,直接使用this可以访问到data中定义的数据,但在vue3不行,因为setup()函数的执行要比created,oncrated函数都要早。
具体使用以下小技巧可以访问到:
<div v-on:click="fun(testdata)"></div> setup(){ const fun=(i)=>{ alert(i) } }, data(){ return{ testdata:1, } }
也可以使用getCurrentInstance方法获取data内的数据(未验证)
<script lang="ts"> import { getCurrentInstance } from "vue"; export default { data() { return { b: "data数据", }; }, setup() { const datab = getCurrentInstance(); async function getdata(){ let dataa=datab.data.b; console.log(dataa) } }, }; </script>
其他知识
样式只在当前页面有效
组件中style标签后面加上
scoped
就可以<style lang="less" scoped></style>