不使用Webpack的Vue传统前端使用方式(一)

本文展示使用传统的前端开发方式使用vuejs,不使用webpack的如何使用vuejs开发前端工程。一方面可以对比两者的差异,一方面学习一种新的思路(或者是老路)。在做一个小型的前端工程时,可以考虑这种轻量化的方案。本示例使用了boostrap、jquery、vue、vue-router组件,创建了一个SPA单页示例。

先闲扯几句。最近vuejs 3.0 开始beta,相信不久(也不好说是多久)就会发布了,性能提升令人期待。由Webpack支撑的前端技术栈,把以往传统的前端开发和发布模式引入了一个新的工程化的阶段。依赖管理、编译、treeshaking等等。对于研发是提升了工程组织维护效率,但是对于用户来说是增加整体拥有成本。

开放共享的互联网正在变得封闭。像jquery、bootstrap这样的组件库都是RELEASE的,为什么还要从源码的层面去引入依赖,然后重新编译和发布。把所有的公共库都打包的vender.js里,明明可以共享CDN的,节省流量的。我注意到这一切好像是从进入移动互联网开始的,也就是用户终端从浏览器更换到了手机。浏览器被组件化到APP中,一切开始私有和封闭起来。

以下是bootstrap v4.x的官方文档,使用CDN直接引入依赖的css和js。

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous">script>

好,回到正文。

我们开始搭建一个工程。考虑到我们需要http的调用,还是得有个服务,这里使用nodejs环境,当然你也可以用nginx,或者其他语言的web appserver,比如tomcat。

初始化工程

新建一个目录demo,使用cnpm init初始化一个工程(或者npm),安装express、axios两个组件库。

$ cnpm init
$ cnpm i -S express axios

然后创建一个public目录,用来放置我们的前端代码,因为不需要编译,都是静态资源。

目录如下:

demo/
├── index.js
├── node_modules/
├── package-lock.json
├── package.json
└── public/

创建一个index.js来启动web服务。

const express = require('express');
const bodyParser = require('body-parser');

const port = 8080;

app = express();
app.use(bodyParser.json());
app.use(express.static('public')); //静态资源目录


app.listen(port,  () => console.log(`Server running: http://localhost:${port}`));

好了,现在运行web服务:

$ node index.js

可以访问了http://localhost:8080/,只不过是一个空的服务。

工程目录public的一般结构示例:

public/
├── css/
│   └── main.css
├── img/
├── index.html
└── js
    ├── lib/
    ├── main.js
    └── vue_com.js

引入js组件库

创建一个页面index.html,组件全是使用CDN的,当然也可以下载到本地,然后引用。

为了不反复贴代码,下面的代码是完整示例:


<html lang="zh-CN">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>DEMOtitle>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="css/main.css">

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js">script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js">script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js">script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
    <script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js">script>
head>

<body>
    <div id="app">div>
    <script src="js/vue_com.js">script>
    <script src="js/vue_hello.js">script>
    <script src="js/vue_app.js">script>
    <script src="js/main.js">script>
body>

html>

接下来我们开始编写各部分的代码,最终的目录和文件如下:

public/
├── css
│   └── main.css
├── index.html
└── js
    ├── lib
    ├── main.js
    ├── vue_app.js
    ├── vue_com.js
    └── vue_hello.js

顺便把自定义css部分,main.css贴一下:

.m-toast-pop {position: fixed; width: 100%;top: 0;bottom: 0;right: 0;overflow: auto;text-align: center; z-index: 9;}      
.m-toast-inner {position: absolute;left:50%;top:50%;width: 100%; transform:translate(-50%,-50%);-webkit-transform:translate(-50%,-50%);text-align: center;}
.m-toast-inner-text{display: inline-block;margin: 0 22px; padding: 19px 21px;font-size: 16px;color: #FFFFFF;letter-spacing: 0;line-height: 22px;background: rgba(0,0,0,0.72);border-radius: 10px;}   
.fade-enter-active, .fade-leave-active {transition: opacity .5s; }
.fade-enter, .fade-leave-to {opacity: 0; }

.topbar {line-height: 39px; border-bottom: 1px solid #eee; }
.topbar ul{margin: 0; padding: 0 5px;}
.topbar li{display: inline-block; padding: 0 5px;}
.router-link-active {color: #666;}

编写vue公用组件

实现一个简易消息提示框组件,toast,公共组件部分可以都放置在vue_com.js中:

Vue.component('toast', {
    template: `
    
        
{{msg}}
`
, data() { return { show: false, msg: '' } }, methods: { showMsg(txt) { this.msg = txt; this.show = true; setTimeout(() => this.show = false, 2000); } } });

这个toast提示框,有Android开发经验的人知道,弹出提示,然后过一会儿自动消失。

我们所有的组件注册基本都使用全局注册的方式。模板直接定义在js里,注意引号是这里使用的ES6中的新加入的单反引号,支持多行字符串。

编写vue页面组件

vue中的模块组织都是由组件来完成的,习惯把页面功能的称为页面组件,其他功能性封装组件叫公用组件。

Vue.component('hello', {
    template: `
    

hello world

`
, data() { return { msg: '' } }, inject: ['toast'], methods: { showText() { this.toast('hello!') } } });

这里页面将会在点击按键时,调用toast组件弹出简易提示框,显示hello消息。toast组件定义在父组件中,见下文。

编写vue入口组件

主界面app组件,文件为vue_app.js

Vue.component('app', {
    template: `
    
  • 首页
  • hello
`
, provide() { return { toast: this.toast } }, methods: { toast: function(msg) { this.$refs.toast.showMsg(msg) } }, });

可以看到使用vue的provide/inject机制,把toast方法暴露给子组件使用。

入口app组件,里面定义的页面的整体布局,路由页面展示区router-view和导航部分。

编写vue应用初始化部分

vue和vue-router的初始化部分,main.js

(function() {
    var router = new VueRouter({
        routes: [
            { path: '/home', component: { template: '

welcome!

'
} }, { path: '/hello', component: Vue.component('hello') } ] }) new Vue({ router, el: '#app', render: h => h(Vue.component('app')) }); })()

这里初始化了路由和vue,把应用入口挂载到id为app的dom元素上。

对于/home使用了一个组件配置对象,这是vue-route支持的,相对于注册了一个局部的组件,vue的组件注册非常灵活。

这里的初始化用闭包,是不把变量暴露到全局,也就是window对象下。

需要注意的是,js引入顺序,main.js放置在最后,也就是所有组件的js的后面。并且是在body的最后面,保证所有的页面dom元素已加载。还记得jquery的ready方法吗,也是保证页面加载完成后的执行的。

$(document).ready(function() {
	//do something
});

现在再到浏览器刷新下刚才的url,可以看到效果了,图就不上了。

下一篇,在这个例子的基础上使用axios组件调用一个后端api。

代码可以在 github上的相应分支vue-demo-no-webpack上找到

你可能感兴趣的:(Vue)