Vue3不再推荐继续使用mixin, 那逻辑复用???

728 阅读1分钟
Vue2大家熟悉的mixins大数用来把组件逻辑提取到可以复用的单元里面,然而mixins的三个主要短板:
    1、不清晰的数据来源(组件出现多个mixin时)
    2、命名空间冲突(合作开发导致)
    3、隐式的跨mixin交流 (多个 mixin 需要依赖共享的属性名来进行相互作用,这使得它们隐性地耦合在一起)
    
所以Vue3其一组合式函数**
  • 组合式函数: 利用Vue的组合式API来封装和复用有状态逻辑的函数,直接理解为组合式函数的形式提取到外部文件中更酷的是: 可嵌套多个组合式函数。一个组合式函数可以调用一个或多个其他的组合式函数,直接上示例1:

    //collection.js 点击收藏
    import { ref, onMounted, onUnmounted } from 'vue'
    
    // 按照惯例,组合式函数名以“use”开头
    export function useCollection() {
        const isCollection = ref<boolean>(false)
        
        // 组合式函数可以随时更改其状态
        function changeCollection(){
            isCollection.value = !isCollection.value
            // 接口
            fetch(...).then()
        }
        
        return {
            isCollection,
            changeCollection
        }
    }
    

在组件中使用的方式:

   <script setup>
       import { useCollection } from '@/common/collection.js'
       
       const { isCollection,  changeCollection } = useCollection()
   </script>
   <template>
       <span :class="['iconfont', isCollection ? 'icon-shoucang' : 'icon-qudiao']" @click="changeCollection"></span>
   </template>
   

示例2: 输入框交互后台动态数据查询

search.js  isRef: 方法判断是否响应式  unref:方法解包可能为ref的值  watchEffect:方法启动一个响应式的effect

 import { ref, isRef, unrec, watchEffect } from 'vue'
 export function useSearch(url, text){
     const data = ref(null)
     const error = ref(null)
     
     const textValue = unref(text)
     
     try{
        await timeout()
        const res = await doSearchFetch(url, textValue)
        data.value = await res.json()
     } catch (e) {
         error.value = e
     }
     
     async function doSearchFetch(){
         data.value = null
         error.value = null
         
         fetch(url, unref(textValue))
             .then((res) => data.value = res)
             .catch((err) => error.value = err)
     }
     
     // 如果value值是一个ref, 则开启响应式的请求
     if(isRef(text)){
         watchEffect(doSearchFetch)
     } esle{
         // 否则只请求一次,避免监听器的额外开销
         doSearchFetch()
     }
     
     return {
        data,
        error
     }
 }
 
 function timeout() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() > 0.3) {
        resolve()
      } else {
        reject(new Error('Error'))
      }
    }, 300)
  })
}
 

组件使用:

 <script setup>
     import { useSearch } from '@/common/search.js'
     const searchValue = ref()
     const { data, error } = useSearch('/api/search', searchValue)
 </script>   
 
 <template>
     <input :value="searchValue" plahoader="请输入查询内容" />
     <ul>
         <li v-for="item in data" :key="item.id">{{ item.lable }}</li>
     </ul>
 </template>