【问题标题】:How to build a Model Layer in Vue3 just like other MVC language?如何像其他 MVC 语言一样在 Vue3 中构建模型层?
【发布时间】:2022-01-19 07:05:18
【问题描述】:

我的名字是 DP,我有 2 年的 Vue2 经验,但我是 Vue3 的新手。我最近正在学习 Vue3,因为我发现“设置(组合 API)”就像我用其他语言做的“控制器(在 MVC 中)”一样,所以我试图以 MVC 方式构建我的测试 Vue3 项目,但我解决一些问题有人可以帮忙吗?谢谢!

MVC 计划

M - use class
V - use <template> ... </template>
C - use setup

我的问题

工作:在 setup() 中使用 loadTopic_inSetup().then() 是有效的,因为 topicList_inSetup 也在 setup() 中定义。

不起作用:在设置中使用 loadTopic_inModel() 不起作用,我猜是某种数据保留问题,因为在控制台中我可以看到已经从 API 获得的数据

如您所见,我不是 js/ts 专家,我是后端开发人员,所以如果您知道如何做,请多多帮助。

顺便说一句,VUE 很受欢迎,我喜欢它。

我的代码

//APIBased.ts

import { ajax } from "@/lib/eeAxios"

export class APIBased {
    //load data with given url and params
    loadData(apiPath: string, params?: object): Promise<any> {
        apiPath = '/v1/'+apiPath
        return ajax.get(apiPath, params)
    }
}

//主题.ts 从“./APIBased”导入 { APIBased }; 从 'vue' 导入 { ref }
export class Topic extends APIBased {
    //try keep data in model
    topicList: any = ref([]);

    constructor() {
        super()
    }

    //direct return ajax.get, let setup do the then+catch
    loadTopic_inSetup() {
        return super.loadData('topics', { t_type_id: 1 })
    }    
    
    //run ajax get set return data to this.topicList, keep data in model
    loadTopic_inModel() {
        super.loadData('topics', { t_type_id: 1 }).then((re) => {
            console.log(re.data)
            this.topicList = re.data
        })
    }
}

//EETest.vue
<template>
  <EELayoutMainLayout>
    <template v-slot:mainContent>
      <h1>{{ "Hello Vue3 !!" }}</h1>

      <hr/>
      {{to.topicList}} //not working... just empty array
      
      <hr/>
      {{topicList_inSetup}} //working... topic list return from API show here.
      
    </template>
  </EELayoutMainLayout>
</template>

<script lang="ts">
import { defineComponent, getCurrentInstance, ref } from 'vue'
import EELayoutMainLayout from '@/components/eeLayout/EELayoutMainLayout.vue'

import { Topic } from "@/models/Topic";

export default defineComponent({
  name: 'EETest',
  props: {
  },
  setup() {
    let topicList_inSetup = ref([])
    
    const to = new Topic()
    
    //try keep data in setup, it's working
    to.loadTopic_inSetup().then((re) => {
      topicList_inSetup.value = re.data
      console.log(re.data)
    })
    
    //try keep data in model, the function is run, api return get, but data not show, even add ref in model
    to.loadTopic_inModel()

    return {
      topicList,
      to,
    }
  },
  components: {
    EELayoutMainLayout,
  },
})

</script>

【问题讨论】:

  • 我在Topic 类中看到的一件事,topicList 是一个引用,因此您需要将响应数据分配给它的值。

标签: model-view-controller axios vuejs3 vue-composition-api


【解决方案1】:

在解决问题之前有一些题外话。也许你是一个 java 开发者。我个人认为用Java思想写前端是不合适的。 vue3的setup的设计更倾向于组合函数式编程

要充分理解为什么需要一些前置知识,ProxyObject的get和set方法
它们对应vue中的两个核心api,reactiveref, 前者只能适用于对象(因为proxy只能代理对象),后者可以适用于任何类型(主要适用于基本的javascript类型,get和set可以适用于任何类型)
您可以修改代码以满足您的期望

loadTopic_inModel() {
   super.loadData('topics', { t_type_id: 1 }).then((re) => {
      console.log(re.data)
      this.topicList.value = re.data
   })
}

你不能直接修改一个 ref 对象,一个解释什么是响应式的测试用例
当调用 ref 函数时,a 就像被包裹在一个具有 value 属性的类中,并且具有 get 和 set 方法

效果函数会调用箭头函数,此时会调用a的get方法,并作为效果函数的依赖进行跟踪,当a发生变化时,会调用a的set方法,它会触发箭头功能, 所以当你直接修改a时,setter方法永远不会触发,视图也不会更新

const a = ref(1)
let dummy
let calls = 0
effect(() => {
  calls++
  dummy = a.value
})
expect(calls).toBe(1)
expect(dummy).toBe(1)
a.value = 2
expect(calls).toBe(2)
expect(dummy).toBe(2)
// same value should not trigger
a.value = 2
expect(calls).toBe(2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多