将 Typescript 与 Laravel 和 Vue.js 一起使用,导入不使其成为 Vue 组件?

Posted

技术标签:

【中文标题】将 Typescript 与 Laravel 和 Vue.js 一起使用,导入不使其成为 Vue 组件?【英文标题】:Using Typescript with Laravel and Vue.js, imports not making it to Vue components? 【发布时间】:2020-07-02 17:54:32 【问题描述】:

我正在尝试使用 Laravel 后端编写 Vue SPA,同时还使用 Typescript 而不是 Raw javascript。我想我很难把头绕在某些事情上,主要是围绕打字稿。显然我需要 Axios,所以我尝试导入它并将其绑定到我的 bootstrap.ts 文件中的窗口,类似于在 Laravel 的默认 bootstrap.js 文件中完成的方式。

资源/js/bootstrap.ts

import 'bootstrap';
import Axios, AxiosStatic from 'axios';

declare global 
    // Extending the DOM Window Interface
    interface Window 
        axios: AxiosStatic;
    

    // Extending querySelector Element
    interface Element 
        content: string;
    


declare var window: Window;
window.axios = Axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

const token: Element | null = document.head.querySelector('meta[name="csrf-token"]');

if (token) 
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
 else 
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token')

然后将其导入我的 app.ts 文件,然后设置 Vue 路由器并导入组件。

资源/js/app.ts

/**
 * First, we will load all of this project's Javascript utilities and other
 * dependencies. Then, we will be ready to develop a robust and powerful
 * application frontend using useful Laravel and JavaScript libraries.
 */

import './bootstrap';
import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

import App from './views/App.vue';
import Welcome from './views/Welcome.vue';
import Dashboard from './views/Dashboard.vue';
import Login from './views/Login.vue';
import Register from './views/Register.vue';

const router = new VueRouter(
    mode: 'history',
    routes: [
        
            path: '/',
            name: 'home',
            component: Welcome
        ,
        
            path: '/login',
            name: 'login',
            component: Login
        ,
        
            path: '/register',
            name: 'register',
            component: Register
        ,
        
            path: '/dashboard',
            name: 'dashboard',
            component: Dashboard
        
    ],
);

const app = new Vue(
    el: '#app',
    components:  App ,
    router,
);

但是,当我尝试在我的 Vue 组件中使用 axios 时,我收到错误 cannot find name 'axios'。当然,我也会收到与隐式任何类型相关的错误,但我知道我为什么会得到这些错误。当然我也记得从 npm 安装 axios。

我将在此处发布 Register.vue 文件以供参考,但是在我想在其中使用 axios 的任何文件中都会遇到类似的错误。

resources/js/views/Register.vue

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card card-default">
                    <div class="card-header">Register</div>

                    <div class="card-body">
                        <form method="POST" action="/register">
                            <div class="form-group row">
                                <label for="name" class="col-md-4 col-form-label text-md-right">Name</label>

                                <div class="col-md-6">
                                    <input id="name" type="text" class="form-control" v-model="name" required autofocus>
                                </div>
                            </div>

                            <div class="form-group row">
                                <label for="email" class="col-md-4 col-form-label text-md-right">E-Mail Address</label>

                                <div class="col-md-6">
                                    <input id="email" type="email" class="form-control" v-model="email" required>
                                </div>
                            </div>

                            <div class="form-group row">
                                <label for="password" class="col-md-4 col-form-label text-md-right">Password</label>

                                <div class="col-md-6">
                                    <input id="password" type="password" class="form-control" v-model="password" required>
                                </div>
                            </div>

                            <div class="form-group row">
                                <label for="password-confirm" class="col-md-4 col-form-label text-md-right">Confirm Password</label>

                                <div class="col-md-6">
                                    <input id="password-confirm" type="password" class="form-control" v-model="password_confirmation" required>
                                </div>
                            </div>

                            <div class="form-group row mb-0">
                                <div class="col-md-6 offset-md-4">
                                    <button type="submit" class="btn btn-primary" @click="handleSubmit">
                                        Register
                                    </button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import  Route  from 'vue-router'

@Component
export default class Register extends Vue
        name: string = ""
        email: string = ""
        password: string = ""
        password_confirmation: string = ""

        handleSubmit(e: UIEvent) 
            e.preventDefault()

            if (this.password === this.password_confirmation && this.password.length > 0)
            
                axios.post('api/register', 
                    name: this.name,
                    email: this.email,
                    password: this.password,
                    c_password : this.password_confirmation
                    )
                    .then((response) => 
                    localStorage.setItem('user',response.data.success.name)
                    localStorage.setItem('jwt',response.data.success.token)

                    if (localStorage.getItem('jwt') != null)
                        this.$router.push('/dashboard', () => this.$router.go(0))
                    
                    )
                    .catch(error => 
                    console.error(error);
                    );
             else 
                this.password = ""
                this.password_confirmation = ""

                return alert('Passwords do not match')
            
        

        beforeRouteEnter (to: Route, from: Route, next: any) 
            if (localStorage.getItem('jwt')) 
                return next('dashboard');
            

            next();
        

</script>

我在这里遗漏了一些明显的东西吗?以错误的方式解决这个问题?以下是一些可能与情况相关的其他杂项文件。

webpack.mix.js

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.ts('resources/js/app.ts', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

tsconfig.json


    "compilerOptions": 
        "target": "es5",
        "strict": true,
        "module": "es2015",
        "moduleResolution": "node",
        "experimentalDecorators": true,
    ,
    "include": [
        "resources/js/**/*"
    ]

资源/js/typings.d.ts

declare module '*.vue' 
    import Vue from 'vue';
    export default Vue;

【问题讨论】:

【参考方案1】:

我也没有让它工作,对我有用的只是在我使用 axios 时在每个组件中导入 axios。

import axios from 'axios';
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
const token = document.head.querySelector('meta[name="csrf-token"]');

if (token) 
    axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
 else 
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');


不会,每次您在其他地方使用 axios 时,仍会设置这些标头。 例如,在您的 Register.vue 中,您只需 import axios from 'axios';

【讨论】:

以上是关于将 Typescript 与 Laravel 和 Vue.js 一起使用,导入不使其成为 Vue 组件?的主要内容,如果未能解决你的问题,请参考以下文章

typescript Laravel Mix的Typscript配置文件

typescript 来自Laravel API的Angular下载文件

将 Angular 1.x 与 TypeScript 1.5 和 SystemJS 一起使用

将 gsap ScrollTrigger 与 React useRef() 和 Typescript 一起使用 - 类型不匹配

typescript Angular Service将FormGroup与LocalStorage同步(获取和设置)

如何将 CSS 模块与 Typescript、React 和 Webpack 一起使用?