Vue 前端未在使用 Rails 作为 api 和 vite 作为前端服务器的应用程序中呈现

问题描述 投票:0回答:1

我正在开发一个应用程序,后端使用 Ruby on Rails,前端使用 Vuejs。 Rails 正在作为 api 被使用。 Vite是前端服务器。 当我启动我的应用程序时,

rails s (in one tab of my console) 
vite dev (in the other)

我只能看到控制器提供的 json,但看不到任何正在渲染的前端。看起来后端和前端没有正确连接。我提供了我认为最重要的文件来解决我的问题。我真的不知道如何解决这个问题。

My_Application
  |-app
    |-controllers
      |-application_controller
    |-models
    .
    .
    .
  |-frontend
    |-components
    |-entrypoints
      |-application.js
      |-router.js
      .
      .
      .
    |-index.html
  |-config
    |-routes.rb
    |-application.rb
    |-vite.json
    .
    .
    .

这是application_controller.rb


    class ApplicationController < ActionController::API
    
      before_action :configure_permitted_parameters, if: :devise_controller?
      before_action :authenticate_user!
      # skip_before_action :verify_authenticity_token if Rails.env.development?
      
      protected
    
      def configure_permitted_parameters
        devise_parameter_sanitizer.permit(:sign_up) do |u|
          u.permit(:first_name, :last_name, :name, :email, :password)
        end
    
        devise_parameter_sanitizer.permit(:account_update) do |u|
          u.permit(:first_name, :last_name, :name, :email, :password, :password_confirmation, :current_password)
        end
      end
    
    
    end

这是index.html


    <!DOCTYPE html>
    <html>
      <head>
        <title>Rails7VueVite</title>
        <meta charset="UTF-8">
            <link rel="preconnect" href="https://fonts.googleapis.com">
            <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
            <link href="https://fonts.googleapis.com/css2?family=Kode+Mono:[email protected]&display=swap" rel="stylesheet">
            <link href="https://fonts.googleapis.com/css2?family=Barriecito&family=Kode+Mono:[email protected]&display=swap" rel="stylesheet">
      </head>
    
      <body>
        <div class="flex flex-col h-screen">
          <main class="flex flex-col">
            <div id="app" class="font-sans"><div>
          </main>
        </div>
        <script type="module" src="/entrypoints/application.js"></script>
      </body>
    </html>

这是application.js


    // application.js
    import { createApp } from 'vue'
    import { createPinia } from "pinia"
    
    import App from '../components/pages/App.vue'
    import router from './router.js'
    import useSessionStore from "../stores/SessionStore.js"
    import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css'
    
    import './main.scss';
    
    const app = createApp(App)
    const pinia = createPinia()
    
    
    // Load JWT from local storage on refresh
    const loadAuthToken = async () => {
      const authToken = localStorage.getItem("authToken")
      const authTokenExists = authToken !== "undefined" && authToken !== null
    
      if (authTokenExists) {
        await useSessionStore(pinia).loginUserWithToken(authToken)
      }
    }
    
    loadAuthToken().then(() => {
      app
        .use(router)
        .use(pinia)
        .mount("#app")
    })
    
    
    app.config.errorHandler = (err, instance, info) => {
        console.log('wrong !!! err =>', err)
        console.log('wrong !!! instance =>', instance)
        console.log('wrong !!! info =>', info)
    }
    if (import.meta.env.DEV) {
        // Enable Vue Devtools in development environment
        app.config.devtools = true;
    }

这是router.js


    // app/javascript/packs/router.js
    import { createRouter, createWebHistory } from 'vue-router'
    import useSessionStore from "../stores/SessionStore"
    import Home from '../components/pages/Home.vue'
    import About from '../components/pages/About.vue'
    import Track from '../components/pages/Track.vue'
    import NewProject from '../components/pages/NewProject.vue'
    import MyTracks from '../components/pages/MyTracks.vue'
    import NewResultTrack from '../components/pages/NewResultTrack.vue'
    import TrackConversation from '../components/conversations/TrackConversation.vue'
    import Messaging from '../components/pages/Messaging.vue'
    import UserForm from '../components/UserForm.vue'
    
    const authGuard = (to, next) => {
      const isLoggedIn = useSessionStore().isLoggedIn
      const requiresAuth = to.meta.requiresAuth
    
      if (isLoggedIn && !requiresAuth) return next({ name: "Home" })
      if (!isLoggedIn && requiresAuth) return next({ name: "Login" })
    
      return next()
    }
    
    const routes = [
        { path: '/', name: 'Home', component: Home },
        { path: '/aboutkkk', component: About },
        { path: '/track/:zeTrackId', name: 'track', component: Track },
        { path: '/new_project', component: NewProject },
        { path: '/my_own_tracks', component: MyTracks },
        { path: '/upload_track/:zeTrackId', name: 'result_track', component: NewResultTrack },
        { path: '/conversation/:conversationId', name: 'conversation', component: TrackConversation },
        { path: '/my_messages', component: Messaging },
        { path: '/login-signin', component: UserForm },
        { path: "/users/sign_in", name: "Login", component: UserForm, meta: { requiresAuth: false }},
        { path: "/users/sign_up",name: "Signup", component: UserForm, meta: { requiresAuth: false }},
        { path: "/users/logout",name: "Logout",meta: { requiresAuth: true },
            beforeEnter: async (_to, _from, next) => {
                await useSessionStore().logout()
                next({ name: "Login" })
            }
        }
    ];
    
    const router = createRouter({
        history: createWebHistory(),
        routes
    })
    
    router.beforeEach((to, _from, next) => {
      authGuard(to, next)
    })
    
    export default router

这是routes.rb


    Rails.application.routes.draw do
      devise_for :users,
            controllers: {
                sessions: "users/sessions",
                registrations: "users/registrations"
            }
    
        namespace :api do
            namespace :v1 do
                resources :chatrooms, only: %i[index] do
                    resources :messages, only: %i[index create]
                end
            end
        end
      resources :tracks
      resources :instruments, only: [:index, :new, :create]
      resources :genres, only: [:index, :new, :create]
      root 'tracks#index'
      get '/index_results/:id', to: 'tracks#index_results', as: 'index_results'
        get '/my_tracks', to: 'tracks#myTracks', as: 'myTracks'
        get "/member-data", to: "members#show"
        get "*path", to: "static#index", constraints: proc { |request| !request.xhr? && request.format.html? }
    
      # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
    
    end

这是应用程序.rb


    require_relative "boot"
    
    require "rails/all"
    
    # Require the gems listed in Gemfile, including any gems
    # you've limited to :test, :development, or :production.
    Bundler.require(*Rails.groups)
    
    module Collaborasound
      class Application < Rails::Application
        config.application_name = Rails.application.class.module_parent_name
        # Initialize configuration defaults for originally generated Rails version.
        config.load_defaults 6.1
    
            config.session_store :cookie_store, key: "_interslice_session"
    
        # Required for all session management (regarless of session_store)
        config.middleware.use ActionDispatch::Cookies
    
        config.middleware.use config.session_store, config.session_options
        # Configuration for the application, engines, and railties goes here.
        #
        # These settings can be overridden in specific environments using the files
        # in config/environments, which are processed later.
        #
        # config.time_zone = "Central Time (US & Canada)"
        # config.eager_load_paths << Rails.root.join("extras")
            # Only loads a smaller set of middleware suitable for API only apps.
        # Middleware like session, flash, cookies can be added back manually.
        # Skip views, helpers and assets when generating a new resource.
        config.api_only = true
      end
    end

这是vite.json


    {
      "all": {
        "sourceCodeDir": "app/frontend",
        "watchAdditionalPaths": []
      },
      "development": {
        "autoBuild": true,
        "publicOutputDir": "vite-dev",
        "port": 3036
      },
      "test": {
        "autoBuild": true,
        "publicOutputDir": "vite-test",
        "port": 3037
      }
    }

这是vite.config.ts


    import { defineConfig } from "vite";
    import vue from "@vitejs/plugin-vue";
    import * as path from "path";
    import FullReload from "vite-plugin-full-reload";
    import RubyPlugin from "vite-plugin-ruby"
    // import path from "path";
    
    export default defineConfig({
      plugins: [
        vue(),
        RubyPlugin(),
        FullReload(["config/routes.rb", "app/views/**/*"], { delay: 250 })
      ],
      resolve: {
        alias: [
          {
            find: "@/lib",
            replacement: path.resolve(__dirname, "./app/frontend/components/lib/")
          },
          {
            find: "@/components",
            replacement: path.resolve(__dirname, "./app/frontend/components/")
          },
          {
            find: '@/entrypoints',
            replacement: path.resolve(__dirname, "./app/frontend/entrypoints")
          }
        ]
      }
    })

ruby-on-rails vuejs3 vite rails-api
1个回答
0
投票

在您发布的代码中,我没有看到任何实际与您的 Rails API 进行通信的内容。

请记住,您的 Vue

router.js
和 Rails
routes.rb
不会自动相互通信。 Vue 是一个单页面应用程序框架,Vue 路由可以引导用户访问不同的 Vue 组件。它不会为您与 Rails API 对话。

我发现您的商店正在使用 Pinia。您可以在此处定义 API 调用。我建议您查看 Pinia 文档,其中包含一些有关如何定义与 API 通信的操作的示例。一个基本的例子可能看起来像:

export const useTracks = defineStore('tracks', {
  state: () => ({
    tracks: null
  }),

  actions: {
    async fetchTodos() {
      try {
        // localhost:3000 is the default Rails port
        const response = await fetch('https://localhost:3000/tracks');

        if (!response.ok) {
          throw new Error('Network error, failed to fetch tracks');
        }

        const data = await response.json();
        this.tracks = data;
      } catch (error) {
        console.error('Error fetching tracks:', error);
      }
    },
  },
})
© www.soinside.com 2019 - 2024. All rights reserved.