vue3开发学习笔记(持续补充中...)

1. setup

组合式api,在before create之前执行( 没法用this ), 属性,方法,生命周期钩子函数都写在这里面,要想在模版中使用setup中定义的属性或方法,记得要return出去

另外,在setup中使用vue的api或者一些函数时,要先引入

import {
      defineComponent, getCurrentInstance, ref, onMounted } from 'vue';

参数: setup( props, context ) { }

  • props 一个对象,里边有父组件向子组件传递的数据,子组件中使用props接受到的所有属性

  • context 上下文对象 setup( props, { attrs, slots, emit } )

    attrs 是属性,相当于this.$attrs

    slots 插槽 相当于this.$slots

    emit 自定义事件 相当于this.$emit

2. 组合Api

  1. ref 定义简单类型的响应式数据

    const name = ref('张三')
    

    另外,ref 获取元素

    vue2中 获取

    直接this.$refs.test

    vue3中 获取

    需要

     setup () {
           
        const test = ref(null)   // 先创建
        onMounted(() => {
            // 挂载之后在onMounted才能获取到
          console.log('test.value', test.value);
        })
      }
    
  2. reactive 定义复杂类型的响应式数据

    const obj = reactive({
           
          name: '张三',
          age: 18
        })
    
  3. toRef 转换响应式对象中某个属性为单独响应式数据

    // 定义响应式数据对象
    const obj = reactive({
           
          name: '张三',
          age: 18
        }) 
    // !!!从响应式数据对象中解构出的属性数据,不再是响应式数据
    //  let { name } = obj 不能直接解构,出来的是一个普通数据
    const name = toRef(obj, 'name') // 这样name 在模版中可以直接使用
    
  4. toRefs 转换响应式对象中所有属性为单独响应式数据,对象成为普通对象

     setup () {
           
        // 1. 响应式数据对象
        const obj = reactive({
           
          name: '张三',
          age: 10
        })
        console.log(obj)
        // 2. 解构或者展开响应式数据对象
        // const {name,age} = obj
        // console.log(name,age)
        // const obj2 = {...obj}
        // console.log(obj2)
        // 以上方式导致数据就不是响应式数据了
       
        const obj3 = toRefs(obj)
        console.log(obj3)
    
        const updateName = () => {
           
          // obj3.name.value = '张三'
          obj.name = '李四'
        }
    
        return {
           ...obj3, updateName}
      }
    
  5. computed 计算属性

    <template>
      <div class="container">
        <div>今年:{
           {
           age}}</div>
        <div>后年:{
           {
           newAge}}</div>
      </div>
    </template>
    <script>
    import {
            computed, ref } from 'vue'
    export default {
           
      name: 'App',
      setup () {
           
        // 1. 计算属性:当你需要依赖现有的响应式数据,根据一定逻辑得到一个新的数据。
        const age = ref(16)
        // 得到后年的年龄
        const newAge = computed(()=>{
           
          // 该函数的返回值就是计算属性的值
          return age.value + 2
        })
        // -------------------------------------------------------
        // 另外还可以设置get,set方法
        // 计算属性高级用法,传入对象
        const newAge = computed({
           
          // get函数,获取计算属性的值
          get(){
           
            return age.value + 2
          },
          // set函数,当你给计算属性设置值的时候触发
          set (value) {
           
            age.value = value - 2
          }
        })
    
        return {
           age, newAge}
      }
    }
    </script>
    
  6. watch 监听器

    监听ref定义的响应式数据

    监听多个响应式数据数据

    监听reactive定义的响应式数据

    监听reactive定义的响应式数据,某一个属性

    深度监听 deep: true

    默认执行 immediate: true

    <template>
      <div class="container">
        <div>
          <p>count的值:{
           {
           count}}</p>
          <button @click="add">改数据</button>
        </div>
        <hr>
        <div>
          <p>{
           {
           obj.name}}</p>
          <p>{
           {
           obj.age}}</p>
          <p>{
           {
           obj.brand.name}}</p>
          <button @click="updateName">改名字</button>
          <button @click="updateBrandName">改品牌名字</button>
        </div>
      </div>
    </template>
    <script>
    import {
            reactive, ref, watch } from 'vue'
    export default {
           
      name: 'App',
      setup () {
           
        const count = ref(0)
        const add = () => {
           
          count.value++
        }
        // 当你需要监听数据的变化就可以使用watch
        // 1. 监听一个ref数据
        // 1.1 第一个参数  需要监听的目标
        // 1.2 第二个参数  改变后触发的函数
        // watch(count, (newVal,oldVal)=>{
           
        //   console.log(newVal,oldVal)
        // })
    
    
        const obj = reactive({
           
          name: 'ls',
          age: 10,
          brand: {
           
            id: 1,
            name: '宝马'
          }
        })
        const updateName = () => {
           
          obj.name = 'zs'
        }
        const updateBrandName = () => {
           
          obj.brand.name = '奔驰'
        }
        // 2. 监听一个reactive数据
        watch(obj, ()=>{
           
          console.log('数据改变了')
        })
    
        watch(()=>obj.brand, ()=>{
           
          console.log('brand数据改变了')
        },{
           
          // 5. 需要深度监听
          deep: true,
          // 6. 默认触发
          immediate: true
        })
    
        // 3. 监听多个数据的变化
        // watch([count, obj], ()=>{
           
        //   console.log('监听多个数据改变了')
        // }) 
    
    
        // 4. 此时监听对象中某一个属性的变化 例如:obj.name 
        // 需要写成函数返回该属性的方式才能监听到
        // watch(()=>obj.name,()=>{
           
        //   console.log('监听obj.name改变了')
        // })
    
        return {
           count, add, obj, updateName, updateBrandName}
      }
    }
    </script>
    
  7. 父子组件之间通讯 props emit

    父子组件之间传值,在vue2中,父传子是通过在子组件中props接受父组件中传递的值,子传父是通过this.$emit 抛出一个事件

    在vue3中,大概也是这样,只是写法不同

    • 父传子 在setup种使用props数据 setup(props){ // props就是父组件数据 }

      <template>
        <div class="container">
          <h1>父组件</h1>
          <p>{
               {
               money}}</p>
          <hr>
          <Son :money="money" />
        </div>
      </template>
      <script>
      import {
                ref } from 'vue'
      import Son from './Son.vue'
      export default {
               
        name: 'App',
        components: {
               
          Son
        },
        // 父组件的数据传递给子组件
        setup () {
               
          const money = ref(100)
          return {
                money }
        }
      }
      </script>
      
      
      <template>
        <div class="container">
          <h1>子组件</h1>
          <p>{
               {
               money}}</p>
        </div>
      </template>
      <script>
      import {
                onMounted } from 'vue'
      export default {
               
        name: 'Son',
        // 子组件接收父组件数据使用props即可
        props: {
               
          money: {
               
            type: Number,
            default: 0
          }
        },
        setup (props) {
               
          // 获取父组件数据money
          console.log(props.money)
        }
      }
      </script>
      
      
    • 子传父 触发自定义事件的时候emit来自 setup(props,{emit}){ // emit 就是触发事件函数 }

      <template>
        <div class="container">
          <h1>父组件</h1>
          <p>{
               {
               money}}</p>
          <hr>
      +    <Son :money="money" @change-money="updateMoney" />
        </div>
      </template>
      <script>
      import {
                ref } from 'vue'
      import Son from './Son.vue'
      export default {
               
        name: 'App',
        components: {
               
          Son
        },
        // 父组件的数据传递给子组件
        setup () {
               
          const money = ref(100)
      +    const updateMoney = (newMoney) => {
               
      +      money.value = newMoney
      +    }
      +    return {
                money , updateMoney}
        }
      }
      </script>
      
      <template>
        <div class="container">
          <h1>子组件</h1>
          <p>{
               {
               money}}</p>
      +    <button @click="changeMoney">50</button>
        </div>
      </template>
      <script>
      import {
                onMounted } from 'vue'
      export default {
               
        name: 'Son',
        // 子组件接收父组件数据使用props即可
        props: {
               
          money: {
               
            type: Number,
            default: 0
          }
        },
        // props 父组件数据
        // emit 触发自定义事件的函数
      +  setup (props, {
                emit}) {
               
          // 获取父组件数据money
          console.log(props.money)
          // 向父组件传值
      +    const changeMoney = () => {
               
            // 消费50元
            // 通知父组件,money需要变成50
      +      emit('change-money', 50)
      +    }
      +    return {
               changeMoney}
        }
      }
      </script>
      
  8. 依赖注入 provide和inject

    使用场景:有一个父组件,里头有子组件,有孙组件,有很多后代组件,共享父组件数据。

    <template>
      <div class="container">
        <h1>父组件 {
           {
           money}} <button @click="money=1000">发钱</button></h1>
        <hr>
        <Son />
      </div>
    </template>
    <script>
    import {
            provide, ref } from 'vue'
    import Son from './Son.vue'
    export default {
           
      name: 'App',
      components: {
           
        Son
      },
      setup () {
           
        const money = ref(100)
        const changeMoney = (saleMoney) => {
           
          console.log('changeMoney',saleMoney)
          money.value = money.value - saleMoney
        }
        // 将数据提供给后代组件 provide
        provide('money', money)
        // 将函数提供给后代组件 provide
        provide('changeMoney', changeMoney)
    
        return {
            money }
      }
    }
    </script>
    <style scoped lang="less"></style>
    
    <template>
      <div class="container">
        <h2>子组件 {
           {
           money}}</h2>
        <hr>
        <GrandSon />
      </div>
    </template>
    <script>
    import {
            inject } from 'vue'
    import GrandSon from './GrandSon.vue'
    export default {
           
      name: 'Son',
      components: {
           
        GrandSon
      },
      setup () {
           
        // 接收祖先组件提供的数据
        const money = inject('money')
        return {
            money }
      }
    }
    </script>
    <style scoped lang="less"></style>
    
    <template>
      <div class="container">
        <h3>孙组件 {
           {
           money}} <button @click="fn">消费20</button></h3>
      </div>
    </template>
    <script>
    import {
            inject } from 'vue'
    export default {
           
      name: 'GrandSon',
      setup () {
           
        const money = inject('money')
        // 孙组件,消费50,通知父组件App.vue组件,进行修改
        // 不能自己修改数据,遵循单选数据流原则,大白话:数据谁定义谁修改
        const changeMoney = inject('changeMoney')
        const fn = () => {
           
          changeMoney(20)
        }
        return {
           money, fn}
      }
    }
    </script>
    <style scoped lang="less"></style>
    

3. inheritAttrs

官方文档,如果你希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false。 what ???

可以这样说,当 inheritAttrs 为false时,在渲染出的dom上,不会有写在 父组件中的 子组件标签上的 属性

如果为默认true, 在渲染出的dom上,就会有这个属性

可以参考 https://www.cnblogs.com/luyuefeng/p/11106172.html

4. getCurrentInstance

​ getCurrentInstance 支持访问内部组件实例

​ 只能在setup 或生命周期钩子中调用

​ 官网文档中给出一个warning

getCurrentInstance 只暴露给高阶使用场景,典型的比如在库中。强烈反对在应用的代码中使用 getCurrentInstance。请不要把 它当作在组合式 API 中获取 this 的替代方案来使用。

可以参考 https://my.oschina.net/u/4355717/blog/4767509

你可能感兴趣的:(vue.js,javascript,前端)