vue3 hooks最佳实践

269 阅读2分钟

大家好!第一次写文章,看到网上很多vue3的hooks写法,但是我觉得总是少点灵魂和感觉,达不到自己和大家心中想要的,这次我就给大家分享一下使用vue3的心得和体会。

1.vue3代码最佳实践

大家请看,引用了尤雨溪写的代码。函数和变量全部都是在20多行之内开始暴露出来,极大的增强代码的阅读速度,并且能够很快的上手,其实很多人也是这么写的,但是是封装成js文件,为了封装而封装得不偿失,等到复用的时候再抽出来就好啦!如果能够帮到你,请给我点个赞谢谢!

<script setup>
import { useQuery, mutate } from 'vue-apollo'
import { ref, reactive, watch, nextTick } from 'vue'
import { onBeforeRouteLeave } from 'vue-router'
// Reusable functions not specific to this component
import { useNetworkState } from '@/functions/network'
import { usePathUtils } from '@/functions/path'
import { resetCwdOnLeave, useCwdUtils } from '@/functions/cwd'
// GraphQL
import FOLDER_CURRENT from '@/graphql/folder/folderCurrent.gql'
import FOLDERS_FAVORITE from '@/graphql/folder/favoriteFolders.gql'
import FOLDER_OPEN from '@/graphql/folder/folderOpen.gql'
import FOLDER_OPEN_PARENT from '@/graphql/folder/folderOpenParent.gql'
import FOLDER_SET_FAVORITE from '@/graphql/folder/folderSetFavorite.gql'
import PROJECT_CWD_RESET from '@/graphql/project/projectCwdReset.gql'
import FOLDER_CREATE from '@/graphql/folder/folderCreate.gql'
// Misc
import { isValidMultiName } from '@/util/folders'
const SHOW_HIDDEN = 'vue-ui.show-hidden-folders'
// Network
const { networkState } = useNetworkState()
// Folder
const { folders, currentFolderData } = useCurrentFolderData(networkState)
const folderNavigation = useFolderNavigation({ networkState, currentFolderData })
const { favoriteFolders, toggleFavorite } = useFavoriteFolders(currentFolderData)
const { showHiddenFolders } = useHiddenFolders()
const createFolder = useCreateFolder(folderNavigation.openFolder)
// Current working directory
resetCwdOnLeave()
const { updateOnCwdChanged } = useCwdUtils()
// Utils
const { slicePath } = usePathUtils()
// Reusable functions specific to this component
function useCurrentFolderData (networkState) {
  const folders = ref(null)
  const currentFolderData = useQuery({
    query: FOLDER_CURRENT,
    fetchPolicy: 'networkState-only',
    networkState,
    async result () {
      await nextTick()
      folders.scrollTop = 0
    }
  }, {})
  return {
    folders,
    currentFolderData
  }
}
function useFolderNavigation ({ networkState, currentFolderData }) {
  // Path editing
  const pathEditing = reactive({
    editingPath: false,
    editedPath: '',
  })
  // DOM ref
  const pathInput = ref(null)
  async function openPathEdit () {
    pathEditing.editedPath = currentFolderData.path
    pathEditing.editingPath = true
    await nextTick()
    pathInput.focus()
  }
  function submitPathEdit () {
    openFolder(pathEditing.editedPath)
  }
  // Folder opening
  const openFolder = async (path) => {
    pathEditing.editingPath = false
    networkState.error = null
    networkState.loading++
    try {
      await mutate({
        mutation: FOLDER_OPEN,
        variables: {
          path
        },
        update: (store, { data: { folderOpen } }) => {
          store.writeQuery({ query: FOLDER_CURRENT, data: { currentFolderData: folderOpen } })
        }
      })
    } catch (e) {
      networkState.error = e
    }
    networkState.loading--
  }
  async function openParentFolder () {
    pathEditing.editingPath = false
    networkState.error = null
    networkState.loading++
    try {
      await mutate({
        mutation: FOLDER_OPEN_PARENT,
        update: (store, { data: { folderOpenParent } }) => {
          store.writeQuery({ query: FOLDER_CURRENT, data: { currentFolderData: folderOpenParent } })
        }
      })
    } catch (e) {
      networkState.error = e
    }
    networkState.loading--
  }
  // Refresh
  function refreshFolder () {
    openFolder(currentFolderData.path)
  }
  return {
    pathInput,
    pathEditing,
    openPathEdit,
    submitPathEdit,
    openFolder,
    openParentFolder,
    refreshFolder
  }
}
function useFavoriteFolders (currentFolderData) {
  const favoriteFolders = useQuery(FOLDERS_FAVORITE, [])
  async function toggleFavorite () {
    await mutate({
      mutation: FOLDER_SET_FAVORITE,
      variables: {
        path: currentFolderData.path,
        favorite: !currentFolderData.favorite
      },
      update: (store, { data: { folderSetFavorite } }) => {
        store.writeQuery({ query: FOLDER_CURRENT, data: { currentFolderData: folderSetFavorite } })
        let data = store.readQuery({ query: FOLDERS_FAVORITE })
        // TODO this is a workaround
        // See: https://github.com/apollographql/apollo-client/issues/4031#issuecomment-433668473
        data = {
          favoriteFolders: data.favoriteFolders.slice()
        }
        if (folderSetFavorite.favorite) {
          data.favoriteFolders.push(folderSetFavorite)
        } else {
          const index = data.favoriteFolders.findIndex(
            f => f.path === folderSetFavorite.path
          )
          index !== -1 && data.favoriteFolders.splice(index, 1)
        }
        store.writeQuery({ query: FOLDERS_FAVORITE, data })
      }
    })
  }
  return {
    favoriteFolders,
    toggleFavorite
  }
}
function useHiddenFolders () {
  const showHiddenFolders = ref(localStorage.getItem(SHOW_HIDDEN) === 'true')
  watch(showHiddenFolders, value => {
    if (value) {
      localStorage.setItem(SHOW_HIDDEN, 'true')
    } else {
      localStorage.removeItem(SHOW_HIDDEN)
    }
  }, { lazy: true })
  return {
    showHiddenFolders
  }
}
function useCreateFolder (openFolder) {
  const showNewFolder = ref(false)
  const newFolderName = ref('')
  const newFolderValid = computed(() => isValidMultiName(newFolderName.value))
  async function createFolder () {
    if (!newFolderValid.value) return
    const result = await mutate({
      mutation: FOLDER_CREATE,
      variables: {
        name: newFolderName.value
      }
    })
    openFolder(result.data.folderCreate.path)
    newFolderName.value = ''
    showNewFolder.value = false
  }
  return {
    showNewFolder,
    newFolderName,
    newFolderValid,
    createFolder
  }
}
</script>