[TOC]

前言:以官方文档为蓝本的Vue学习过程中,需要的一些细节以及实际开发中遇到的总结点。

Vue的学习过程中,主要分几个大块:

  • 基础知识:框架自行的一些语法(官网里面的基础
  • 组件相关:尤其是组件之间的各类通信方式,在写/抽离组件里面经常用到,单独一篇文章总结。

官方文档:

“他们的依赖”指的是data数据域中的data数据,如果其变动,计算属性值才会变

  • 方法不存在缓存

    计算属性(computed)和侦听器(watch)的使用

  • 侦听器更用于异步或是开销较大的操作

文档: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当中:

  1. beforeCreate:在实例初始化之后,数据观测和事件配置之前被调用
  2. created:在实例创建完成后被立即调用
  3. beforeMount:在挂载开始之前被调用
  4. mounted:el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子
  5. beforeUpdate:数据更新时调用,发生在虚拟DOM打补丁之前
  6. updated:由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子
  7. beforeDestroy:实例销毁之前调用
  8. 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>

执行结果如下:
image.png

Vue3.x相交Vue2.x的API差异

  • 参考教程:Vue3.0 新特性以及使用经验总结

    组合式API

    62783021-7ce24400-ba89-11e9-9dd3-36f4f6b1fae2.png62783026-810e6180-ba89-11e9-8774-e7771c8095d6.png

    defineComponent({})

    服务于typescript项目,defineComponent 本身的功能很简单,但是最主要的功能是为了 ts 下的类型推导。对于一个 ts 文件,如果我们直接写
    export default {}
    
    对于编辑器而言,{} 只是一个 Object 的类型,无法有针对性的提示我们对于 vue 组件来说 {} 里应该有哪些属性。但是增加一层 defineComponet 的话,
    export default defineComponent({})
    
    这时,{} 就变成了 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>
    
    image.png

    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>