Node环境Vue全家桶实战

环境搭建

推荐用Vue-Cli搭建项目。如果打算集成第三方框架,如Element-UI、Antd等,就用第三方提供的脚手架。

项目结构

image.png
刚撸完的一个完整项目
image.png
用到的一些技术

  • dist:运行yarn build后生成的目录,不需要运行在node环境,可以直接用浏览器打开
  • node_modules:依赖
  • public:这里面我只留了一个index.html
  • api:调用接口的方法
  • components:组件,也可以简单理解成能够被多个vue文件复用的vue文件
  • routers:这里面也是vue文件,很多人弄不清它和components的区别,虽然都是vue文件,但是routers里面的vue文件能够被vue-router控制,做页面跳转(hash路由)
  • store:为Vuex存放的模块化数据,这里做的比较简单,只存了方法名,便于commit
  • util:一些工具类
  • App.vue:就放一个router-view标签做路由,不干其它事
  • main.js:主方法,在这里初始化vue实例,将vue-router和vuex集成到vue实例上
  • router.js:初始化vue-router
  • store.js:初始化vuex
  • vue.config.js:可以覆盖webpack的一些配置

其它的没啥好介绍的了

技术细节

Router创建

import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from './routers/Home'
import FabanSearch from './routers/FaBanSearch'
import FaBanList from './routers/FaBanList'

Vue.use(VueRouter)

const routers = [
  {
    path: "/",
    component: Home,
    meta: {
      title: '查询类型'
    }
  },
  {
    path: '/fabansearch',
    component: FabanSearch,
  },
  {
    path: '/fabanlist',
    component: FaBanList,
  },
]

export default new VueRouter({
  routes: routers,
})
  • 先用Vue.use()一下Vue-Router对象
  • path是路径,可以通过router-link(a)标签或者js路由
  • component就是router文件夹里的vue文件

Vuex创建

先来看store文件夹有一个mutationType.js文件,这里面定义了vuex的mutations的方法名

export default {
  SAVE_TEST: 'saveTest',
}

再来看store.js怎么写的

import Vue from 'vue'
import Vuex from 'vuex';

import mutationType from './store/mutationType'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    test: [],
  },
  mutations: {
    [mutationType.SAVE_TEST](state, test) {
      state.test = test
    }
  },
})
  • state就像vue实例里面的data,但是vuex里面的这个state可以让所有vue组件访问。而vue里面的data只能自己玩。
  • mutations:修改state的。当然也可以直接修改state,但是通过mutations修改的state会在vue-devtool中显示状态流,方便debug。

Vue集成Vue-Router、Vuex

在main.js中

// vue
import Vue from 'vue'

// 路由
import router from './router'

// vuex
import store from './store'

// vant
import Vant from 'vant';
import 'vant/lib/index.css';

// index
import App from './App.vue'

Vue.config.productionTip = false

Vue.use(Vant)

// 将router和store放进去就行了
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

Api接口方法定义

import axios from 'axios'
import qs from 'qs'

import { baseUrl } from './baseOption'

// 基础配置
const http = axios.create({
  method: 'POST',
  baseURL: '/',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
  },
})

/**
 * 获取进站证发班明细列表
 * @param {Object} param 查询参数
 */
export async function listFaban(param = { page: 1, rows: 10 }) {
  const resp = await http({
    url: '/api/test1',
    data: qs.stringify(param),
  })
  return resp.data
}

/**
 * 获取所有区域列表和场站列表
 */
export async function listArea() {
  const resp = await http({
    url: '/api/test2',
  })
  return resp.data
}
  • 在vue方法中可以把方法声明成async,然后await调用就可以将异步方法当同步方法用了,非常方便
    async initSelect() {
      const data = await listArea();
      ...
    }
    
  • qs用来将对象转成url参数的

Vue组件的定义

在定义Vue组件的时候切记不能再组件中使用Vuex或者其它第三方的数据,它最好只用data(自己的数据)和props(父组件传过来的数据)的数据
Vue组件如果要修改Vuex里的数据,最好是父组件在子组件监听一个方法,子组件通过emit方法触发父组件的方法,父组件通过回调修改vuex数据。

Vue子组件为了复用性最好是不要与父组件之外的数据有交互,component文件夹就是我们定义的子组件,这些组件可以在多处被重复使用

上个代码,自己理解
component中的组件

<template>
  <div class="list">
    <van-list
      v-model="loading"
      :finished="dataList.length >= total"
      finished-text="没有更多了"
      @load="onLoad"
    >
      <van-cell v-for="(item, index) in dataList" :key="index">
        <slot name="default">
          <div class="container">
            <div class="item" style="background: #eee;">第{{index+1}}条 共{{total}}条数据</div>
            <div class="item" v-for="(itemMap, itemIndex) in item" :key="itemIndex">
              <span>{{itemMap.key}}</span>
              <span>{{itemMap.value}}</span>
            </div>
          </div>
        </slot>
      </van-cell>
    </van-list>
  </div>
</template>

<script>
export default {
  name: "List",
  props: ["dataList", "onLoad", "total"],
  data() {
    return {
      loading: false
    };
  }
};
</script>

<style scoped>
.container {
  width: 100%;
  background-color: #ffffff;
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
}

.container .item {
  padding: 5px 10px;
  display: flex;
  flex-basis: 100%;
  justify-content: space-between;
}

.container .item span {
  flex: 1;
}
</style>

router中的组件,List在components中声明后使用,List组件就可以根据父组件传过来的数据进行渲染。只要父组件(调用方)保证数据正确,而不需要在意vuex或者其它数据源的数据是否正确。List就相当于一个功能组件,和util差不多的意思。

<template>
  <div id="faBanList">
    <List :dataList="fabanListFormat" :onLoad="listFaban" :total="fabanTotal" ref="list" />
  </div>
</template>

<script>
import List from "../components/List";

export default {
  ...
  // 声明
  components: {
    List: List
  },
  ...
}
</script>

打包

这里说个小坑,我在打包的时候,dist/index.html的路径默认引入的是绝对路径,如果文件不是放在服务器的根目录下,会导致css、js找不到。所以我后来加了个vue.config.js文件

module.exports = {
  publicPath: './'
}

把webpack的默认配置改下,默认是/,就会用相对路径访问资源文件
yarn build就可以打包了

# Vue 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×