v-on 处理程序变量 this 中的 VueJS 错误。未定义

VueJS Error in v-on handler variable this. is undefined

在具有 MongoDB/Express 后端 api 的 VueJS 中工作,尝试使用单个字段 url 添加 post 新记录到书签模型,但出现错误我试图传递的 url 字段是 undefined。我之前已经将此模式用于 api 调用,没有遇到任何问题,所以我不确定这次发生了什么。

从控制台:

Error in v-on handler (Promise/async): "Error: Request failed with             status code 500"

在网络选项卡中:

{"errors":{"message":"Cannot read property 'url' of undefined","error":{}}}

这里是组件:

<template>
  <div class="bookmarks">
    <h1>Add a Bookmark</h1>
    <div class="form">
      <div>
        <input type="text" placeholder="Enter a URL" v-model="url">
      </div>
      <div>
        <button class="app_post_btn" @click="addBookmark">Save</button>
      </div>
    </div>
  </div>
</template>

<script>
import BookmarksService from '@/services/BookmarksService'
export default {
  name: 'NewBookmark',

  data () {
    return {
      url: ''
    }
  },
  methods: {
    async addBookmark () {
      await BookmarksService.addBookmark({
        url: this.url
      })
      this.$router.push({ name: 'Bookmarks' })
    }
  }
}
</script>

<style type='text/css'>
.form input,
.form textarea {
  width: 500px;
  padding: 10px;
  border: 1px solid #e0dede;
  outline: none;
  font-size: 12px;
}
.form div {
  margin: 20px;
}

.app_post_btn {
  background: #4d7ef7;
  color: #fff;
  padding: 10px 80px;
  text-transform: uppercase;
  font-size: 12px;
  font-weight: bold;
  width: 520px;
  border: none;
  cursor: pointer;
}
</style>

对后端的 api 调用来自服务文件夹,因此在 BookmarksService.js:

import Api from '@/services/Api'

export default {
  fetchBookmarks () {
    return Api().get('bookmarks')
  },

  addBookmark (params) {
    return Api().post('bookmarks', params)
  }
...

Api.js:

import axios from 'axios'
const token = localStorage.getItem('token')

export default () => {
  return axios.create({
    baseURL: 'http://localhost:8000/api',
    headers: {
      'Content-Type': 'application/json',
      token: token,

    }
  })
}

为了回应下面的评论,这里是请求信息:

Request URL: http://localhost:8000/api/bookmarks
Request Method: POST
Status Code: 500 Internal Server Error
Remote Address: [::1]:8000
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 75
Content-Type: application/json; charset=utf-8
Date: Fri, 05 Apr 2019 16:47:01 GMT
ETag: W/"4b-DnvHolHvXjMbxmLeqrleWSWRA0Q"
X-Powered-By: Express
Provisional headers are shown
Accept: application/json, text/plain, */*
authorization: Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJvbmVAZ21haWwuY29tIiwiaWQiOiI1YzlmOTcxY2E3YzIyNTc1ZTFjYzkwMDUiLCJleHAiOjE1NTk2NjY3ODcsImlhdCI6MTU1NDQ4Mjc4N30.zlrqFfj2r7K_1iAVm7m2w_kUeqFH3ZvsDJkIK7UOUu8
Content-Type: application/json
Origin: http://localhost:8080
Referer: http://localhost:8080/
token: Token undefined
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
{url: "http://axios.com"}
url: "http://axios.com"

在服务器端:

这是 post 路线:

const mongoose = require('mongoose');
const passport = require('passport');
const router = require('express').Router();
const auth = require('../auth');
const Bookmarks = mongoose.model('Bookmarks');

//POST new user route (optional, everyone has access)
router.post('/', auth.required, (req, res, next) => {
  const userId = req.user.id;
  const bookmark = req.body.bookmark;

  if(!bookmark.url) {
    return res.status(422).json({
      errors: {
        url: 'is required',
      },
    });
  }

  bookmark.userId = userId;
  const finalBookmark = new Bookmarks(bookmark);

  return finalBookmark.save()
    .then(() => res.json({ bookmark: finalBookmark }));
});

...

来自 Express 应用程序的 app.js 文件:

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const session = require('express-session');
const cors = require('cors');
const mongoose = require('mongoose');
const errorHandler = require('errorhandler');

//Configure mongoose's promise to global promise
mongoose.promise = global.Promise;

//Configure isProduction variable
const isProduction = process.env.NODE_ENV === 'production';

//Initiate our app
const app = express();

//Configure our app
app.use(cors());
app.use(require('morgan')('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ secret: 'bookmarks-darius', cookie: { maxAge: 60000 }, resave: false, saveUninitialized: false }));

if(!isProduction) {
  app.use(errorHandler());
}

//Configure Mongoose
mongoose.connect('mongodb://localhost/bookmarks', { useNewUrlParser: true });
mongoose.set('debug', true);

//Models & routes
require('./models/Users');
require('./models/Bookmarks');
require('./config/passport');
app.use(require('./routes'));

// express doesn't consider not found 404 as an error so we need to handle 404 explicitly handle 404 error
app.use(function(req, res, next) {
  if (err) {
    next(err);
  } else { // no error thrown by another route, so we must not have found a route, therefore return a 404
    let err = new Error('Not Found');
    err.status = 404;
    next(err);
  }
});

//Error handlers & middlewares
if(!isProduction) {
  app.use(function (err, req, res, next) {
    res.status(err.status || 500);

    res.json({
      errors: {
        message: err.message,
        error: err,
      },
    });
  });
}

app.use(function (err, req, res, next) {
  res.status(err.status || 500);

  res.json({
    errors: {
      message: err.message,
      error: {},
    },
  });
});

app.listen(8000, () => console.log('Server running on http://localhost:8000/'));

请参阅下面的代码段。始终验证来自正文的任何​​ 属性。

router.post('/', auth.required, (req, res, next) => {
  const userId = req.user.id;
  const bookmark = req.body.bookmark; <---- bookmark is undefined

  if(!bookmark.url) { <---- undefined.url -> Error.
    return res.status(422).json({
      errors: {
        url: 'is required',
      },
    });
  }

  // ...
});

来自您的前端的请求正文不是您所期望的。
这里的主要问题是,在 vue.js 组件的 addBookmark 函数中,您传递的对象只有 属性 'url',而在您的后端服务中,您期望的是 'bookmark' 对象,其中包含 属性 'url'。 您也可以在请求正文中看到它:{url: "http://axios.com"} 将您的组件代码更改为

async addBookmark () {
  await BookmarksService.addBookmark({
    bookmark: {
               url: this.url
           }
  })
  this.$router.push({ name: 'Bookmarks' })
}

应该可以。你应该得到这样的东西 { bookmark: {url: "http://axios.com"} }。 无论如何验证来自请求正文的任何​​ 属性 正如 Phil 所说始终是您应该遵循的好习惯。