【问题标题】:Asynchronously mount function异步挂载功能
【发布时间】:2021-06-19 23:23:14
【问题描述】:

在渲染组件之前,我需要从 api 获取一些数据。我正在尝试使用 axios (apiClient),但它需要等待,因为它是一个承诺。

如果我将setup 函数设置为异步,我的模板将不会呈现。如果我尝试在async/await 块内设置data 变量,则模板显然会在承诺返回响应之前呈现。 如何从我的 API 中获取数据,然后渲染我的模板(已经用 OnMounted() 尝试过)

<script>
import apiClient from '@/services/axios'
import store from 'store'
import { SearchOutlined } from '@ant-design/icons-vue'
import { defineComponent, reactive, ref } from 'vue'
import {  onMounted } from 'vue'

var data = []; // needs to receive the api response

export default defineComponent({
  components: {
    SearchOutlined,
  },
  setup() {    
     response = apiClient.get('/gift/list', { headers: { 'Authorization': 'Bearer' + store.get('token') }})
     data = response.data // set data with api response value
    console.log(data)

    const state =  reactive({
      searchText: '',
      searchedColumn: '',
    })

    const searchInput = ref()

    const columns = [
      {
        title: 'Number',
        dataIndex: 'number',
        key: 'number',
        slots: {
          filterDropdown: 'filterDropdown',
          filterIcon: 'filterIcon',
          customRender: 'customRender',
        },
        onFilter: (value, record) =>
          record.number
            .toString()
            .toLowerCase()
            .includes(value.toLowerCase()),
        onFilterDropdownVisibleChange: visible => {
          if (visible) {
            setTimeout(() => {
              console.log(searchInput.value)
              searchInput.value.focus()
            }, 0)
          }
        },
      },
      {
        title: 'Month',
        dataIndex: 'month',
        key: 'month',
        slots: {
          filterDropdown: 'filterDropdown',
          filterIcon: 'filterIcon',
          customRender: 'customRender',
        },
        onFilter: (value, record) =>
          record.month
            .toString()
            .toLowerCase()
            .includes(value.toLowerCase()),
        onFilterDropdownVisibleChange: visible => {
          if (visible) {
            setTimeout(() => {
              searchInput.value.focus()
            })
          }
        },
      },
      {
        title: 'Year',
        dataIndex: 'year',
        key: 'year',
        slots: {
          filterDropdown: 'filterDropdown',
          filterIcon: 'filterIcon',
          customRender: 'customRender',
        },
        onFilter: (value, record) =>
          record.year
            .toString()
            .toLowerCase()
            .includes(value.toLowerCase()),
        onFilterDropdownVisibleChange: visible => {
          if (visible) {
            setTimeout(() => {
              searchInput.value.focus()
            })
          }
        },
      },
            {
        title: 'Price',
        dataIndex: 'price',
        key: 'price',
        slots: {
          filterDropdown: 'filterDropdown',
          filterIcon: 'filterIcon',
          customRender: 'customRender',
        },
        onFilter: (value, record) =>
          record.price
            .toString()
            .toLowerCase()
            .includes(value.toLowerCase()),
        onFilterDropdownVisibleChange: visible => {
          if (visible) {
            setTimeout(() => {
              searchInput.value.focus()
            })
          }
        },
      },

      {
        title: 'Company',
        dataIndex: 'company',
        key: 'company',
        slots: {
          filterDropdown: 'filterDropdown',
          filterIcon: 'filterIcon',
          customRender: 'customRender',
        },
        onFilter: (value, record) =>
          record.company
            .toString()
            .toLowerCase()
            .includes(value.toLowerCase()),
        onFilterDropdownVisibleChange: visible => {
          if (visible) {
            setTimeout(() => {
              searchInput.value.focus()
            })
          }
        },
      },

        {
        title: 'Seller',
        dataIndex: 'addedBy',
        key: 'addedBy',
        slots: {
          filterDropdown: 'filterDropdown',
          filterIcon: 'filterIcon',
          customRender: 'customRender',
        },
        onFilter: (value, record) =>
          record.addedBy
            .toString()
            .toLowerCase()
            .includes(value.toLowerCase()),
        onFilterDropdownVisibleChange: visible => {
          if (visible) {
            setTimeout(() => {
              searchInput.value.focus()
            })
          }
        },
      },
    ]

    const handleSearch = (selectedKeys, confirm, dataIndex) => {
      confirm()
      console.log(selectedKeys[0])
      state.searchText = selectedKeys[0]
      state.searchedColumn = dataIndex
    }

    const handleReset = clearFilters => {
      clearFilters()
      state.searchText = ''
    }

    return {
      data,
      columns,
      handleSearch,
      handleReset,
      searchText: '',
      searchInput: null,
      searchedColumn: '',
    }
  },
})
</script>
<style scoped>
.highlight {
  background-color: rgb(255, 192, 105);
  padding: 0px;
}
</style>

【问题讨论】:

    标签: vue.js vuejs3


    【解决方案1】:

    创建一个ref,在收到 API 响应时异步设置:

    import apiClient from '@/services/axios'
    import { defineComponent, ref, onMounted } from 'vue'
    
    export default defineComponent({
      setup() {
        const myData = ref([])
    
        onMounted(async () => {
          const response = await apiClient.get(...)
          myData.value = response.data
        })
    
        return { myData }
      }
    })
    

    demo

    【讨论】:

      【解决方案2】:

      解决此问题的一种简单方法是将isLoading 添加到您的data 并将其设置为true

      然后,当您取回数据时,您将设置this.isLoading = false

      然后简单地将您的组件包装在 v-if="!isLoading" 中。

      【讨论】:

        猜你喜欢
        • 2021-07-16
        • 2019-11-21
        • 2015-02-10
        • 1970-01-01
        • 2021-05-24
        • 1970-01-01
        • 2017-02-25
        • 2021-11-28
        • 2021-12-18
        相关资源
        最近更新 更多