前端开发框架搭建步骤

  • Post author:
  • Post category:其他




1.安装node.js

https://nodejs.org/en/

node.js自带npm工具,如果觉得npm下载资源太慢,可继续安装cnpm

npm install -g cnpm



2.安装webpack

npm install webpack -g

验证是否安装成功

webpack -v



3.安装vue-cli脚手架

vue-cli 是用 node 编写的命令行工具,我们需要进行全局安装。

npm install --global vue-cli

验证是否安装成功

vue -V//命名可以得到vue的版本号信息



4.初始化一个vue项目

Vue2.0:使用cd命令找到项目需要放置的文件夹,这里以D盘的【Project/web】为例子

D:
cd Project/web 
vue init webpack  itemname[项目名]

项目的参数设置

Project name 可不设置,初始化时已经定义了【项目名】项目名不能大写,不能使用中文

Project description 【项目描述】

Author【作者】

Vue build【】https://www.jianshu.com/p/466510d84e36 根据文章描述,推荐使用‘Runtime-Only’

https://blog.csdn.net/qq_37339364/article/details/82931180 根据该文章,Runtime Only相比Runtime+Compiler更加轻量,但是缺点是不能够编译jsx,在vue源码中,无论是render函数,还是template最终都是编译成render函数进行渲染的,所以,使用Runtime Only有时需要自己手动配置webpack对模板语法进行编译。常用的就是Runtime+Compiler,不需要自己手写render。

Install vue-router【安装 vue-router路由管理工具】选yes,vue-router用于单页面应用控制页面跳转

Use ESLint to lint your code?【使用ESLint检查语法错误】新手对ES6不熟一般选No,不然一直报错,调试很费事

Set up unit tests【创建单元测试】选yes;单元测试主要运用在大型项目或者多人合作开发的情况,暂定先安装

Pick a test runner【选择单元测试的工具】一般选jest

Setup e2e tests with Nightwatch【E2E(End To End)即端对端测试(用户真实场景),属于黑盒测试】,选yes

should we run ‘npm install’?选yes,use NPM,关于yarn,可参考https://www.jianshu.com/p/254794d5e741

Vue3.0

vue create hello-world



5.安装jquery

npm install jquery --save

下载完成后,检查node_modules发现自动生成jquery文件夹

检查根目录下的package.json,看是否有jquery依赖,没有的话加上(必须添加)

注:此处用了save安装,所以dependencies中有jquery依赖,而devDependencies中不存在

"dependencies": {
    "vue": "^2.5.2",
    "vue-router": "^3.0.1",
    "jquery":"^3.3.1"//版本号在jquery安装成功后,cmd上自动显示
  },

save和save-dev的区别

如果你的项目是发布到npm的一个包,
那么这个包的package.json中的dependencies中的依赖是会被下载下来到这个包的node_modules文件夹中的(如果你的项目本身没有这个依赖),而devDependencies不会。

举个例子:
我发布了一个组件A,它有dependencies:lodash和devDependencies:moment。
那么,如果你的项目npm install 了组件A。
除非你的项目也依赖了lodash并且版本一致,那么项目的node_modules/A下会有一个node_modules,里面会有lodash。
而 moment,则无论如何也不会出现在你的项目中。

至于一般的项目,不管你是安装在dev还是dependencies中,安装的时候都会安装,打包的时候都会被打进去的,区分依赖只是为了让项目看起来更加清晰。

编辑webpack.base.conf.js

‘use strict’前添加

var webpack=require('webpack')

在这里插入图片描述

在module.exports里面加入plugins项:

plugins: [ 
  new webpack.ProvidePlugin({ 
    $:"jquery", 
    jQuery:"jquery", 
    "windows.jQuery":"jquery" 
  	}) 
]  

在这里插入图片描述

在main.js中引用

import $ from 'jquery'

测试jquery是否成功,在app.vue中

$(function(){
alert('123')
})



6.安装bootstrap

npm install bootstrap@3.3.0  -save-dev 

main.js中引入

import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'//js文件按需引入,如果不需要使用则不必引入

也可将css、fonts、js三个文件夹取出,放入src/assets路径中

import './assets/css/bootstrap.min.css'
import './assets/js/bootstrap.min.js'//js文件按需引入,如果不需要使用则不必引入



7.引入less

安装

npm install less less-loader --save-dev

检查package.json devDependencies是否有less依赖,没有的话加上

"less": "^3.9.0",
"less-loader":"^4.1.0"

为什么安装less选择save-dev?

因为less是我们在开发中使用的而非在生产中使用,所以就不将之记录在 dependencies .在开发过程中我们需要使用less-loader将less文件编译成css文件,编译完成后发布到生产环境(服务器)后就不需要使用了。



dependencies和devDependencies的区别?

  • devDependencies:生产环境使用
  • dependencies:线上环境使用

例如:比如 我们安装 js的压缩包gulp-uglify 时,我们采用的是 “npm install –save-dev gulp-uglify ”命令安装,因为我们在发布后用不到它,而只是在我们开发才用到它。webpack,gulp等打包工具,这些都是我们开发阶段使用的,代码提交线上时,不需要这些工具,所以我们将它放入devDependencies即可,但是像jquery这类插件库,如果我们不把他打入线上代码中,那么项目就可能报错,无法运行,所以类似这种项目必须依赖的插件库,我们则必须打入dependencies中

测试less是否引入成功

//在asset里新建theme.less文件
//测试内容为
@color:orange;
 .hello {
    color: @color;
    font-size: 0.45rem;
    h2 {
      color: @color;
    }
  }
//在main.js中引入
import './assets/theme.less'
 在浏览器中观察效果

注:

由于已经在webpack中配置了,所以这里不需要引入任何less文件,包括less.js

参考链接:

vue-cli构建项目使用 less

初次接触less,引入时出现一些错误,解决方法记录如下

npm install style-loader --save-dev
main.js中引入less文件书写方式改为
import '!style-loader!css-loader!less-loader!./assets/文件名.less'



8.引入Mock.js做接口数据测试使用

npm install mockjs --save-dev
npm install axios --save-dev

axios的作用是拦截ajax请求,并返回mock构造的数据,达到模拟后台接口的目的

步骤:

1.建立目录结构

src>axios>api.js

【定义请求拦截、响应拦截,自定义一个axios的“ajax响应”】

components>mock.vue

【需要使用模拟接口数据的组件】

mock.js

【定义接口数据、Mock.mock()生成简单的api文档】

在这里插入图片描述

api.js:

import axios from 'axios'
 
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
 
// 请求拦截器
axios.interceptors.request.use(function(config) {
    return config;
  }, function(error) {
    return Promise.reject(error);
  })
  // 响应拦截器
axios.interceptors.response.use(function(response) {
  return response;
}, function(error) {
  return Promise.reject(error);
})
 
// 封装axios的post、get、put、patch请求
export function fetch(url,params,method) {
  if(method.toLowerCase() === 'get'){
    return new Promise((resolve, reject) => {
    axios.get(url, params)
      .then(response => {
        resolve(response.data);
      })
      .catch((error) => {
        reject(error);
      })
    })
  }
  else if(method.toLowerCase() === 'post'){
    return new Promise((resolve, reject) => {
    axios.post(url, params)
      .then(response => {
        resolve(response.data);
      })
      .catch((error) => {
        reject(error);
      })
    })
  }
  else if(method.toLowerCase() === 'put'){
    return new Promise((resolve, reject) => {
    axios.put(url, params)
      .then(response => {
        resolve(response.data);
      })
      .catch((error) => {
        reject(error);
      })
    })
  }
  else if(method.toLowerCase() === 'patch'){
     return new Promise((resolve, reject) => {
    axios.patch(url, params)
      .then(response => {
        resolve(response.data);
      })
      .catch((error) => {
        reject(error);
      })
    })
  }
}
 
export default {
  mockdata(url,params,method) {
    return fetch(url,params,method);
  }
}

mock.js:

// 'Boolean': Random.boolean,
// 可以生成基本数据类型
// 'Natural': Random.natural(1, 10),
// 生成1到100之间自然数
// 'Integer': Random.integer(1, 100),
// 生成1到100之间的整数
// 'Float': Random.float(0, 100, 0, 5),
// 生成0到100之间的浮点数,小数点后尾数为0到5位
// 'Character': Random.character(),
// 生成随机字符串,可加参数定义规则
// 'String': Random.string(2, 10),
// 生成2到10个字符之间的字符串
// 'Range': Random.range(0, 10, 2),
// 生成一个随机数组
// 'Date': Random.date(),
// 生成一个随机日期,可加参数定义日期格式
// 'Image': Random.image(Random.size, '#02adea', '缩略图'),
// Random.size表示将从size数据中任选一个数据
// 'Color': Random.color(),
// 生成一个颜色随机值
// 'Paragraph': Random.paragraph(2, 5),
//生成2至5个句子的文本
// 'Name': Random.name(),
// 生成姓名
// 'Url': Random.url(),
// 生成web地址
// 'Address': Random.province()
// 生成地址

import Mock from 'mockjs' // 引入mockjs
 
const Random = Mock.Random // Mock.Random 是一个工具类,用于生成各种随机数据
 
let data = [] // 用于接受生成数据的数组
let size = [
  '300x250', '250x250', '240x400', '336x280', 
  '180x150', '720x300', '468x60', '234x60', 
  '88x31', '120x90', '120x60', '120x240', 
  '125x125', '728x90', '160x600', '120x600', 
  '300x600'
] // 定义随机值
for(let i = 0; i < 10; i ++) { // 可自定义生成的个数
  let template = {
    'Id':i.toString(),//编号
    'Name': Random.name(), // 生成姓名
    'Boolean': Random.boolean, // 可以生成基本数据类型
    'Integer': Random.integer(1, 100), // 生成1到100之间的整数
    'Date': Random.date(), // 生成一个随机日期,可加参数定义日期格式
    'Address': Random.province() // 生成地址
  }
  data.push(template)
}

let destroyData = function(options){
    let rtype = options.type.toLowerCase();
    console.log(options)
    switch (rtype) {
        case 'get':
            break;
        case 'post':
            let ids = JSON.parse(options.body); // 获取请求的ids,将options.body转换为JSON对象
            console.log("ids",ids)
            ids.map(function(item){
                 data = data.filter(function (val) {
                return val.Id != item; // 过滤掉前台传过来的id对应的相应数据,并重新返回
                });
            })
            return true;
            break;
    }
     
}

Mock.mock('/data/query', /get|post/i, data) // 根据数据模板生成模拟数据
Mock.mock('/data/destroy', 'post', destroyData) // 根据数据模板生成模拟数据

mock.vue

<template>
  <div>
  <input type="text">
  <button @click="">增加</button>
  <button @click="">查询</button>
  <button @click="destroyData()">删除</button>
  <button @click="">修改</button>

  <ul>
    <li v-for="item in lists">{{item.Id}}--{{item.Address}} 
    <button @click="addArrItem(item.Id,destroyArr);destroyFunc();">删除</button></li>
  </ul>
  </div>
</template>
<script>
import api from './../axios/api.js'
export default {
  name: 'Mock',
  data () {
    return {
      lists:"",
      api:{
        query:'/data/query',
        create:'/data/create',
        destroy:'/data/destroy',
        modify:'/data/modify'
      },
      destroyArr:[],
      createArr:[],
      modifyArr:[]
    }
  },
  created () {
   this.queryFunc(this.api.query,this)
   console.log('this.destroyArr',typeof(this.destroyArr))
   // this.destroyData()
   // console.log('this.list',this.list)
  },
  methods: {
    addArrItem:function(item,arr){
        if(arr.includes(item)){ 
          }
        else {
          arr.push(item)
        }
    },
    queryFunc: function(url,obj) {
       queryData(url,obj)
    },
    createFunc:function(){
      
    },
    destroyList:function(arr){
      var  lists =this.lists
       arr.map(function(item){
                lists = lists.filter(function (val) {
                 return val.Id != item; // 过滤掉前台传过来的id对应的相应数据,并重新返回
                 });
            })
       this.lists = lists;
       this.destroyArr = [];
    },
    destroyFunc:function(){
        let url = this.api.destroy;
        let arr = this.destroyArr;
        let callback = this.destroyList
        if(this.destroyArr.length>0){ 
         destroyData(url,arr,callback) 
        }
        else {}
    }
  }
}

function queryData(url,obj){
     api.mockdata(url,'','get')
      .then(res => {
        console.log('queryData结果',res);
        obj.lists = res
      })
}

function destroyData(url,params,callback){
  api.mockdata(url,params,'post')
      .then(res => {
        if(res===true){
          callback(params)
        }
        else{
          console.log('删除不成功,请检查网络')
        }
        return res;
      })
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>


最后,别忘了在main.js里引入mock.js

require('./mock.js')



以下步骤是根据项目需求引入UI框架如 ant design、element ui 、kendo ui

可根据实际情况操作或跳过



9.引入element-ui

npm i element-ui -S

main.js中引入

完整引入:

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'//注意源文件夹及源文件名有些是theme-default
Vue.use(ElementUI)

按需引入(推荐):

安装babel-plugin-component

npm install babel-plugin-component -D

修改.babelrc文件【原plugins里插入该数组值即可】

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}
{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime", [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
    ]
}

建立路径 src>element>index.js

index.js:

// 导入自己需要的组件
import { Select, Option, OptionGroup, Input, Tree, Dialog, Row, Col ,Button} from 'element-ui'
const element = {
  install: function (Vue) {
    Vue.use(Select)
    Vue.use(Option)
    Vue.use(OptionGroup)
    Vue.use(Input)
    Vue.use(Tree)
    Vue.use(Dialog)
    Vue.use(Row)
    Vue.use(Col)
    Vue.use(Button)
  }
}
export default element

main.js中引入

import element from './element/index'
Vue.use(element)

在所有页面可以直接使用特定标签调用组件



10.引入ant-design-vue

npm install ant-design-vue --save

配置按需加载

引入【babel-plugin-import】

npm i babel-plugin-import -D

修改.babelrc文件 ,plugin插入设置项

["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }]

建立路径src>antd>index.js

import { DatePicker ,Button} from 'ant-design-vue';
const antd = {
  install: function (Vue) {
    Vue.use(DatePicker)
    Vue.use(Button)
  }
}
export default antd

main.js中

import antd from './antd/index'
Vue.use(antd)



11.引入kendo ui(kendo for vue)

npm install --save @progress/kendo-ui
npm install --save @progress/kendo-theme-default//安装默认的主题,主题可选其他

按项目需要引入相应的组件,

kendo UI for Vue所有组件链接


如,项目需要使用kendo 的grid

npm install --save @progress/kendo-grid-vue-wrapper
npm install --save @progress/kendo-datasource-vue-wrapper

在main.js中引入依赖

import '@progress/kendo-ui'
//考虑到客户端加载速度,可不全部引入,只引入项目需要的js文件如
import '@progress/kendo-ui/js/kendo.grid.js'

引入样式文件

import '@progress/kendo-theme-default/dist/all.css'

在需要的运用该组件的地方引入组件,如,test.vue里引入

import Vue from 'vue'
import '@progress/kendo-ui/js/kendo.grid.js'
import { Grid, GridInstaller} from '@progress/kendo-grid-vue-wrapper'
import { DataSource,DataSourceInstaller} from '@progress/kendo-datasource-vue-wrapper'
Vue.use(GridInstaller)
Vue.use(DataSourceInstaller);

测试kendo ui for vue在页面上的效果


<template>
<el-tabs type="border-card">
  <el-tab-pane>
    <span slot="label"><i class="el-icon-date">已完成</i></span>
    <div id="vueapp" class="vue-app">
    <kendo-datasource ref="datasource1"
                        :transport-read-url="'https://demos.telerik.com/kendo-ui/service/Products'"
                        :transport-read-data-type="'jsonp'"
                        :transport-update-url="'https://demos.telerik.com/kendo-ui/service/Products/Update'"
                        :transport-update-data-type="'jsonp'"
                        :transport-destroy-url="'https://demos.telerik.com/kendo-ui/service/Products/Destroy'"
                        :transport-destroy-data-type="'jsonp'"
                        :transport-create-url="'https://demos.telerik.com/kendo-ui/service/Products/Create'"
                        :transport-create-data-type="'jsonp'"
                        :transport-parameter-map="parameterMap"
                        :schema-model-id="'ProductID'"
                        :schema-model-fields="schemaModelFields"
                        :batch='true'

                        :page-size='20'>
    </kendo-datasource>

    <kendo-grid :height="600"
                :data-source-ref="'datasource1'"
                :pageable='true'
                :editable="'inline'"
                :filterable="true"
                :sortable="true"
                :groupable="true"
                :selectable="'row'"
                :change="showDetails"
                :excel-all-pages ="true"
                :toolbar= '[
                "create",
                "excel",
                "pdf",
                "表单填写链接",
                "协同",
                "分派",
                "批量导出附件"
                ]'
                :excel-file-name="'Kendo UI Grid Export.xlsx'"
                :excel-proxy-URL="'https://demos.telerik.com/kendo-ui/service/export'"
                :excel-filterable="true"
                >
        <kendo-grid-column :field="'ProductName'"
                            :width="220"></kendo-grid-column>
        <kendo-grid-column :field="'UnitPrice'"
                           :title="'Unit Price'"
                           :format="'{0:c}'"
                           :width="220"
                           ></kendo-grid-column>
        <kendo-grid-column :field="'UnitsInStock'"
                           :title="'Units In Stock'"
                           :width="220"
                           ></kendo-grid-column>
        <kendo-grid-column :field="'Discontinued'"
                            :width="220"
                           ></kendo-grid-column>
         <kendo-grid-column :command="['edit', 'destroy',{ text: '重做',click: showDetails }]"
                           :title="'操作'"
                           :width="240"
                           :locked="true"
                           :lockable="false"
                           ></kendo-grid-column>
    </kendo-grid>
</div>

  </el-tab-pane>
    <el-tab-pane>
      <span slot="label"><i class="el-icon-date">未完成</i></span>未完成收集列表
  </el-tab-pane>
</el-tabs>
</template>
<script>
import Vue from 'vue'
import '@progress/kendo-ui/js/kendo.grid.js'
import { Grid, GridInstaller} from '@progress/kendo-grid-vue-wrapper'
import { DataSource,DataSourceInstaller} from '@progress/kendo-datasource-vue-wrapper'
Vue.use(GridInstaller)
Vue.use(DataSourceInstaller);

  export default {
    data() {
      return {
        activeName: 'second',
         schemaModelFields: {
            ProductID: { editable: false, nullable: true },
            ProductName: { validation: { required: true } },
            UnitPrice: { type: 'number', validation: { required: true, min: 1 } },
            Discontinued: { type: 'boolean' },
            UnitsInStock: { type: 'number', validation: { min: 0, required: true } }
            }
      };
    },
    methods: {
      showDetails:function(e){
        e.preventDefault();
            var grid = this.$refs.grid.kendoWidget();
            // var dataItem = grid.dataItem($(e.currentTarget).closest("tr"));
            alert(grid);
      },
      parameterMap: function(options, operation) {
            if (operation !== 'read' && options.models) {
                return { models: kendo.stringify(options.models) };
            }
        }
    }
  };
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>



11. kendo for vue汉化

main.js中引入

import '@progress/kendo-ui/js/cultures/kendo.culture.zh-CN.js'
import '@progress/kendo-ui/js/messages/kendo.messages.zh-CN.js'

刚接触kendo时遇到汉化不成功的情况,解决方案是main.js中添加

kendo.culture("zh-CN")



12.配置kendo ui的excel导出功能

可根据项目实际情况决定是否略过此步骤

常规方法(不起作用)

安装jszip.js并引入

npm install jszip
import 'jszip/dist/jszip.js'

解决方案:index.html中引入

<script src="http://cdnjs.cloudflare.com/ajax/libs/jszip/2.4.0/jszip.js"></script>
或下载到本地引入
<script src="../static/jszip.js"></script>



版权声明:本文为weixin_44596285原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。