Meteor中集成Vue注意事项

49 篇文章 0 订阅
18 篇文章 0 订阅

meteor_vue_jest 单元测试案例,采用mock拦截函数执行,模拟返回数据
源码 https://gitee.com/618859/meteor_vue_test_jest
更多jest知识请看 https://www.jestjs.cn/docs/mock-functions

intro 常规项目搭建问题

场景1:

如果你发现有一个旧的meteor项目的版本是1.8.1的,是在2019年5月前创建的

你现在2021年10月,还想创建一个1.8.1的meteor项目,可以通过指定版本号来创建项目,如下:
meteor create vue-meteor-app --release 1.8.1

然后:

但是当你创建好项目,想通过在命令行输入meteor来运行时,发现报错了。

Uncaught Error: jQuery not found

他说你缺少jquery这个包,而且你不能通过npm i jquery来安装

而必须通过meteor add jquery这个命令来添加jquery这个包

meteor add jquery

好的,现在项目能正常运行了。

场景2:

但是当你信心满满地按照官网的文档在meteor中集成vue框架时,发现又报错了

While loading plugin vue-component from package akryum:vue-component: Cannot find module

你就会想,项目版本一样都是1.8.1,步骤流程也是按照官网来的,为什么2019年创建时就可以,而现在2021年创建就不行了呢?到底哪里改变了。

后来发现,原来是安装vue转换必备插件akryum:vue-component的时候,版本发生改变了。

通过查看2019年的旧项目
项目根目录/.meteor/versions文件
发现akryum:vue-component@0.14.3

另一个

通过查看2021年的新创建的项目
项目根目录/.meteor/versions文件
发现akryum:vue-component@0.15.3

结论:是插件版本发生改变了。0.14.3才能搭配1.8.1使用的,若是0.15.3就会报错。因此指定版本安装插件即可。
meteor add akryum:vue-component@=0.14.3

更多cmd命令,可以通过meteor add --help查看

到此时,在meteor中集成vue框架就成功了。

后面就跟着官网的步骤操作即可。感慨良多!

Integrating Vue With Meteor

To start a new project:

meteor create vue-meteor-app --release 1.8.1

To install Vue in Meteor, you should add it as an npm dependency:

meteor npm install --save vue

To support Vue’s Single File Components with the .vue file extensions, install the following Meteor package created by Vue Core developer Akryum (Guillaume Chau).

meteor add akryum:vue-component

如果项目运行不起来,应该是akryum:vue-component的版本和项目的版本1.8.1不搭配。

因此要指定akryum:vue-component的版本安装即可,如下:

meteor add akryum:vue-component@=0.14.3

You will end up with at least 3 files:

  1. a /client/App.vue The root component of your app
  2. a /client/main.js Initializing the Vue app in Meteor startup
  3. a /client/main.html containing the body with the #app div

We need a base HTML document that has the app id. If you created a new project from meteor create ., put this in your /client/main.html.

<body>
  <div id="app"></div>
</body>

You can now start writing .vue files in your app with the following format. If you created a new project from meteor create ., put this in your /client/App.vue.

<template>
  <div>
    <p>This is a Vue component and below is the current date:<br />{{date}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      date: new Date(),
    };
  }
}
</script>

<style scoped>
  p {
    font-size: 2em;
    text-align: center;
  }
</style>

You can render the Vue component hierarchy to the DOM by using the below snippet in you client startup file. If you created a new project from meteor create ., put this in your /client/main.js.

import Vue from 'guide/site/content/vue';
import App from './App.vue';
import './main.html';

Meteor.startup(() => {
  new Vue({
    el: '#app',
    ...App,
  });
});

Run your new Vue+Meteor app with this command: NO_HMR=1 meteor

Using Meteor’s data system

One of the biggest advantages of Meteor is definitely it’s realtime data layer. It allows for so called full-stack reactivity and optimistic UI functionality. To accomplish full-stack reactivity, Meteor uses Tracker. In this section we will explain how to integrate Meteor Tracker with Vue to leverage the best of both tools.

  1. Install the vue-meteor-tracker package from NPM:
meteor npm install --save vue-meteor-tracker

Next, the package needs to be plugged into Vue as a plugin. Add the following to your /client/main.js:

import Vue from 'vue';
import VueMeteorTracker from 'vue-meteor-tracker'; // import the integration package!
import App from './App.vue';
import './main.html';

Vue.use(VueMeteorTracker);                         // Add the plugin to Vue!

Meteor.startup(() => {
  new Vue({
    el: '#app',
    ...App,
  });
});

Example app

If you’ve followed the integration guide, then your Vue application shows the time it was loaded.

Let’s add some functionality that makes this part dynamic. To flex Meteor’s plumbing, we’ll create:

  1. A Meteor Collection called Time with a currentTime doc.
  2. A Meteor Publication called Time that sends all documents
  3. A Meteor Method called UpdateTime to update the currentTime doc.
  4. A Meteor Subscription to Time
  5. Vue/Meteor Reactivity to update the Vue component

The first 3 steps are basic Meteor:

  1. In /imports/collections/Time.js
Time = new Mongo.Collection("time");
  1. In /imports/publications/Time.js
Meteor.publish('Time', function () {
  return Time.find({});
});
  1. In /imports/methods/UpdateTime.js
Meteor.methods({
  UpdateTime() {
    Time.upsert('currentTime', { $set: { time: new Date() } });
  },
});

Now, let’s add these to our server. First remove autopublish so our publications matter:

meteor remove autopublish

For fun, let’s make a settings.json file:

{ "public": { "hello": "world" } }

Now, let’s update our /server/main.js to use our new stuff:

import { Meteor } from 'meteor/meteor';

import '/imports/collections/Time';
import '/imports/publications/Time';
import '/imports/methods/UpdateTime';

Meteor.startup(() => {
  // Update the current time
  Meteor.call('UpdateTime');
  // Add a new doc on each start.
  Time.insert({ time: new Date() });
  // Print the current time from the database
  console.log(`The time is now ${Time.findOne().time}`);
});

Start your Meteor app, your should see a message pulling data from Mongo. We haven’t made any changes to the client, so you should just see some startup messages.

meteor
  1. and 5) Great, let’s integrate this with Vue using Vue Meteor Tracker and update our /client/App.vue file:
<template>
  <div>
    <div v-if="!$subReady.Time">Loading...</div>
    <div v-else>
      <p>Hello {{hello}},
        <br>The time is now: {{currentTime}}
      </p>
      <button @click="updateTime">Update Time</button>
      <p>Startup times:</p>
      <ul>
        <li v-for="t in TimeCursor">
          {{t.time}}  -  {{t._id}}
        </li>
      </ul>
      <p>Meteor settings</p>
      <pre><code>
        {{settings}}
      </code></pre>
    </div>
  </div>
</template>

<script>
import '/imports/collections/Time';

export default {
  data() {
    console.log('Sending non-Meteor data to Vue component');
    return {
      hello: 'World',
      settings: Meteor.settings.public,   // not Meteor reactive
    }
  },
  // Vue Methods
  methods: {  
    updateTime() {
      console.log('Calling Meteor Method UpdateTime');
      Meteor.call('UpdateTime');          // not Meteor reactive
    }
  },
  // Meteor reactivity
  meteor: {
    // Subscriptions - Errors not reported spelling and capitalization.
    $subscribe: {
      'Time': []
    },
    // A helper function to get the current time
    currentTime () {
      console.log('Calculating currentTime');
      var t = Time.findOne('currentTime') || {};
      return t.time;
    },
    // A Minimongo cursor on the Time collection is added to the Vue instance
    TimeCursor () {
      // Here you can use Meteor reactive sources like cursors or reactive vars
      // as you would in a Blaze template helper
      return Time.find({}, {
        sort: {time: -1}
      })
    },
  }
}
</script>

<style scoped>
  p {
    font-size: 2em;
  }
</style>

Restart your server to use the settings.json file.

meteor --settings=settings.json 

Then refresh your browser to reload the client.

You should see:

  • the current time
  • a button to Update the current time
  • startup times for the server (added to the Time collection on startup)
  • The Meteor settings from your settings file

Excellent! That’s a tour of some of Meteor’s features, and how to integrate with Vue. Have a better approach? Please send a PR.

Style Guide and File Structure

Like code linting and style guides are tools for making code easier and more fun to work with.

These are practical means to practical ends.

  1. Leverage existing tools
  2. Leverage existing configurations

Meteor’s style guide and Vue’s style guide can be overlapped like this:

  1. Configure your Editor
  2. Configure eslint for Meteor
  3. Review the Vue Style Guide
  4. Open up the ESLint rules as needed.

Application Structure is documented here:

  1. Meteor’s Application Structure is the default start.
  2. Vuex’s Application Structure may be interesting.

SSR and Code Splitting

Vue has an excellent guide on how to render your Vue application on the server. It includes code splitting, async data fetching and many other practices that are used in most apps that require this.

Basic Example

Making Vue SSR to work with Meteor is not more complex then for example with Express. However instead of defining a wildcard route, Meteor uses its own server-render package that exposes an onPageLoad function. Every time a call is made to the server side, this function is triggered. This is where we should put our code like how its described on the VueJS SSR Guide.

To add the packages, run:

meteor add server-render
meteor npm install --save vue-server-renderer

then connect to Vue in /server/main.js:

import { Meteor } from 'meteor/meteor';
import Vue from 'vue';
import { onPageLoad } from 'meteor/server-render';
import { createRenderer } from 'vue-server-renderer';

const renderer = createRenderer();

onPageLoad(sink => {
  console.log('onPageLoad');
  
  const url = sink.request.url.path;
  
  const app = new Vue({
    data: {
      url
    },
    template: `<div>The visited URL is: {{ url }}</div>`
  });

  renderer.renderToString(app, (err, html) => {
    if (err) {
      res.status(500).end('Internal Server Error');
      return
    }
    console.log('html', html);
    
    sink.renderIntoElementById('app', html);
  })
})

Luckily Akryum has us covered and provided us with a Meteor package for this: akryum:vue-ssr allows us to write our server-side code like below:

import { VueSSR } from 'meteor/akryum:vue-ssr';
import createApp from './app';

VueSSR.createApp = function () {
  // Initialize the Vue app instance and return the app instance
  const { app } = createApp(); 
  return { app };
}
Server-side Routing

Sweet, but most apps have some sort of routing functionality. We can use the VueSSR context parameter for this. It simply passes the Meteor server-render request url which we need to push into our router instance:

import { VueSSR } from 'meteor/akryum:vue-ssr';
import createApp from './app';

VueSSR.createApp = function (context) {
  // Initialize the Vue app instance and return the app + router instance
  const { app, router } = createApp(); 
  
  // Set router's location from the context
  router.push(context.url);
  
  return { app };
}

更多资料请看meteor官网https://guide.meteor.com/vue.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值