最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue3进阶-组合式API

    正文概述 掘金(未知本尊)   2021-06-23   921

    前言:

    最近刚弄明白什么是组合式API,什么是选项式API,使用vue2.x这么多年,居然不知道一直在使用的居然是选项式API,以此文对这两个知识点做个总结,纪念自己的无知。

    选项式API VS 组合式API

    1.vue2中的选项式 API (options API)

    页面使用methods、watch、computed等来处理页面逻辑,vue2中的常规格式,不做过多说明。

    export default{
        data(){
            
        },
        //方法
        methods:{
            
        },
        //观察属性
        watch:{
            
        },
        //计算属性
        computed:{
            
        }
    }
    

    为什么使用组合式API

    选项式 API,看起来结构很清晰,当随着业务功能不断增加,代码不断迭代,methods、watch、computed中的代码会不断增加,可能一个vue中包含几个功能,这些功能在methods等内是零散的,当进行bug修复或者添加新功能时带来的工作量会很大,基于这些问题,vue3的组合式API应运而生。

    2. vue3中的组合式API

    引入vue官方示例,setup内的部分为组合式API

    export default {
      props: {
        user: { type: String }
      },
      setup(props) {
        console.log(props) // { user: '' }
    
        return {} // 这里返回的任何内容都可以用于组件的其余部分
      }
      // 组件的“其余部分”
    }
    

    setup参数

    1.props

    父组件传入的props

    示例:
    export default {
      props: {
        title: String
      },
      setup(props) {
        console.log(props.title) //父组件传入的title值
      }
    }
    

    2.context

    示例:
    export default {
      setup(props, context) {
        // Attribute (非响应式对象)
        console.log(context.attrs) //包含除props以外的参数,与vue2中的this.$attrs功能一致
    
        // 插槽 (非响应式对象)
        console.log(context.slots)//包含插槽,与this.$slots功能一致
    
        // 触发事件 (方法)
        console.log(context.emit)//触发事件,与this.$emit方法一致
      }
    }
    

    前置知识点:

    vue3支持tree-shaking(死代码消除),因此vue2中挂载在vue上的全局方法现在必须单独引入才能使用。

    vue 2.x
    this.$nextTich(()=>{
        
    });
    
    vue 3
    import { nextTick } from 'vue'
    nextTick(()=>{
        
    })
    

    setup什么时候触发

    在组件创建之前执行,props被解析,然后执行setup并将props传入方法,由于执行setup时组件实例尚未创建,所以setup内无法使用this,并且无法访问methodswatchcomputed内的方法及属性。

    setup使用

    1. 响应式变量

    setup内使用ref函数实现变量的响应式,并使用return返回变量,供给模板内使用。

    未使用ref

    示例:
    <template>
      <div>name:{{name}}</div>
      <button @click="updateName">修改姓名</button>
    </template>
    
    <script>
    export default {
      name: "test",
      setup(){
        let name = '';
        let updateName = ()=>{
          name = 'xiaoming';
          console.log("修改名字",name)
        }
        return {name,updateName}
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    由于变量是未响应的,所以点击修改触发方法,修改后的值并没有更新到dom中。

    使用ref

    示例:
    <template>
      <div>name:{{name}}</div>
      <button @click="updateName">修改姓名</button>
    </template>
    
    <script>
    import {ref} from 'vue'
    export default {
      name: "test",
      setup(){
        let name = ref('')
        console.log(name); //{value:''}
        let updateName = ()=>{
          name.value = 'xiaoming';
          console.log("修改名字",name)
        }
        return {name,updateName}
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    使用ref方法定义变量后,返回的是一个对象,如果需要修改变量的值需要使用变量.value修改变量的值。

    2. setup内使用watch

    示例:
    <template>
      <div>name:{{name}}</div>
      <button @click="updateName">修改姓名</button>
    </template>
    
    <script>
    import {ref,watch} from 'vue'
    export default {
      name: "test",
      setup(){
        let name = ref('')
        console.log(name);
        let updateName = ()=>{
          name.value = 'xiaoming';
          console.log("修改名字",name)
        }
        //计算属性观察name变化
        watch(name,(newVal,oldVal)=>{
          console.log("newVal",newVal) //xiaoming
          console.log("oldVal",oldVal) // ''
        })
        return {name,updateName}
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    3. setup内使用computed

    示例:
    <template>
      <div>name:{{name}}</div>
      <div>{{nowName}}</div>
      <button @click="updateName">修改姓名</button>
    </template>
    
    <script>
    import {ref,computed} from 'vue'
    export default {
      name: "test",
      setup(){
        let name = ref('')
        console.log(name);
        let updateName = ()=>{
          name.value = 'xiaoming';
          console.log("修改名字",name)
        }
        //使用计算属性返回
        let nowName = computed(()=>{
          return `现在的名字是:${name.value}`
        })
        return {name,updateName,nowName}
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    4. setup内触发生命周期函数

    选项式API与对应的组合式API生命周期

    选项式 APIHook inside setup
    beforeCreateNot needed*createdNot needed*beforeMountonBeforeMountmountedonMountedbeforeUpdateonBeforeUpdateupdatedonUpdatedbeforeUnmountonBeforeUnmountunmountedonUnmountederrorCapturedonErrorCapturedrenderTrackedonRenderTrackedrenderTriggeredonRenderTriggered

    选项式API的生命周期钩子函数与组合式API的触发时机一致,书写方法有区别,下面列了几个常用的生命周期钩子函数的定义方式。

    示例:
    <template>
      <div>name:{{name}}</div>
      <div>{{nowName}}</div>
      <button @click="updateName">修改姓名</button>
    </template>
    
    <script>
    <!--引入所需内置函数-->
    import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated,ref} from 'vue'
    export default {
      name: "test",
      setup(){
        //挂载前
        onBeforeMount(()=>{
          console.log("onBeforeMount")
        })
        //挂载后
        onMounted(()=>{
          console.log("onMounted")
        })
        //修改前
        onBeforeUpdate(()=>{
          console.log("onBeforeUpdate")
        })
        //修改后
        onUpdated(()=>{
          console.log("onUpdated")
        })
        let name = ref('')
        console.log(name);
        let updateName = ()=>{
          name.value = 'xiaoming';
          console.log("修改名字",name)
        }
        return {name,updateName}
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    5. 依赖注入( Provide / Inject)

    父组件将参数注入provide,子、孙组件使用inject,这里使用官方示例

    父组件:
    
    <template>
      <MyMarker />
    </template>
    
    <script>
    import { provide } from 'vue'
    import MyMarker from './MyMarker.vue
    
    export default {
      components: {
        MyMarker
      },
      setup() {
        //向子组件及孙子组件注入两个参数,分别是地址及坐标,一个变量,一个对象
        provide('location', 'North Pole')
        provide('geolocation', {
          longitude: 90,
          latitude: 135
        })
      }
    }
    </script>
    
    子组件:
    
    <script>
    import { inject } from 'vue'
    
    export default {
      setup() {
        //引入父组件注入的变量
        const userLocation = inject('location', 'The Universe')
        const userGeolocation = inject('geolocation')
        
        return {
          userLocation,
          userGeolocation
        }
      }
    }
    </script>
    

    6. 依赖注入响应式

    上面注入的参数如果发生变动,子组件内引入的参数并不会变化,接下来将参数动态化。

    子组件
    
    <template>
      <MyMarker />
    </template>
    
    <script>
    import { provide, reactive, ref } from 'vue'
    import MyMarker from './MyMarker.vue
    
    export default {
      components: {
        MyMarker
      },
      setup() {
        <!--ref上面已经介绍过-->
        const location = ref('North Pole')
        <!--reactive用法与ref相同,不过ref针对的是基本数据类型,而reactive针对的是引用数据类型-->
        const geolocation = reactive({
          longitude: 90,
          latitude: 135
        })
    
        provide('location', location)
        provide('geolocation', geolocation)
      }
    }
    </script>
    

    如果要确保注入的参数不被子组件修改,可以在注入时使用readonly避免子组件修改参数

    父组件
    
    <template>
      <MyMarker />
    </template>
    
    <script>
    import { provide, reactive, readonly, ref } from 'vue'
    import MyMarker from './MyMarker.vue
    
    export default {
      components: {
        MyMarker
      },
      setup() {
        const location = ref('North Pole')
        const geolocation = reactive({
          longitude: 90,
          latitude: 135
        })
        <!--readonly使子组件无法修改父组件注入的参数-->
        provide('location', readonly(location))
        provide('geolocation', readonly(geolocation))
      }
    }
    </script>
    

    结语:

    至此组合式API基本介绍完毕,在开发过程中还是需要自己选择是使用选项式API还是使用组合式API来开发,需要结合自己的使用场景做出选择。


    起源地下载网 » vue3进阶-组合式API

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元