1. vue项目1

适合有点基础的人看,完整的移动端项目构建,包括路由组件、vuex管理、axios封装、登录持久化、权限等
重点不是业务,是项目的架构和思路

vue create vue-project  // 创建项目

1. 配置scss

    1. 在assets文件夹中新增common.scss文件,配置一些公共样式
$color: #fff;
$background: #2a2a2a;
    1. 安装插件,自动加载scss资源,这样不用每个页面都 @import 导入文件
vue add style-resources-loader
// 后续选择:
y
scss
    1. 配置信息
// vue.config.js
const path = require('path')

module.exports = {
  pluginOptions: {
    "style-resources-loader": {
      preProcessor: "scss",  // 在每个页面自动引入scss变量
      patterns: [path.resolve(__dirname, 'src/assets/common.scss')],
    },
  },
};
    1. 验证使用
// App.vue
<template>
  <div id="app">hello</div>
</template>

<style lang="scss">
#app {
  color: $color;
  background: $background;
}
</style>

2. 移动端适配

    1. 安装插件
npm i postcss-plugin-px2rem lib-flexible
    1. 配置文件
// main.js
import 'lib-flexible';  // 对应设置根的字体
// App.vue
// width 根据vue.config.js中配置的写,37.5
<style lang="scss">
* {
  padding: 0;
  margin: 0;
}
#app {
  color: $color;
  background: $background;
  width: 375px;
}
</style>
// vue.config.js 新增以下css部分代码 (配置完后,重启服务)
module.exports = {
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          require("postcss-plugin-px2rem")({
            rootValue: 37.5,  // 表示设计稿的大小 375,750 设置 75rem
          })
        ]
      }
    }
  }
};

3. 安装vant 和 axios

npm i vant axios
// main.js
// 全局加载,实际开始最好按需加载
import Vant from 'vant';
import 'vant/lib/index.css';

Vue.use(Vant);

4. 配置路由

    1. 创建页面
// views 文件夹下新增:home/index.vue  lesson/index.vue  profile/index.vue
// 三个index.vue分别写一个简单的模板
<template>
  <div>home</div>
</template>
    1. 配置路由
// router/index.js  新增以下代码
import Home from '@/views/home/index.vue'

// 自动生成路由 不建议路由自动配置,可配置性比较低(批注、钩子)
const routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/lesson',
    name: 'lesson',
    component: () => import('@/views/lesson/index.vue')
  },
  {
    path: '/profile',
    name: 'profile',
    component: () => import('@/views/profile/index.vue')
  }
];
// App.vue 文件添加 router-view
<div id="app">
  <router-view />
</div>

访问:http://localhost:8080/lesson 验证

5. 处理加载状态

    1. 配置loading组件
// src/components/loading.vue
<template>
  <van-loading type="spinner" />
</template>
    1. 处理加载
// src/utils/loadable.js
import LoadingComponent from '@/components/loading.vue'

const loadable = (asyncFunc) => {
  let component = () => ({  // 最终切换的时候会采用这个组件
    component: asyncFunc(),
    loading: LoadingComponent,  // 只是为了增加loading效果
  })
  return {  // loadable 执行完毕后,返回一个组件
    render(h) {
      return h(component)
    }
  }
}

// 路由切换,异步加载的loading,处理白屏问题
export default loadable
  1. 路由设置
// src/router/index.js
import loadable from '@/utils/loadable';

  {
    path: '/lesson',
    name: 'lesson',
    component: loadable(() => import('@/views/lesson/index.vue'))
  },
  {
    path: '/profile',
    name: 'profile',
    component: loadable(() => import('@/views/profile/index.vue'))
  }
  1. 验证
    把网络设置Fast 3G,切换页面,可以看到加载效果

6. 头部组件实现

    1. 头部组件
// src/views/home/home-header.vue  子组件
<template>
  <div class="home-header">
    <img src="@/assets/logo.png" alt="" />
    <van-dropdown-menu>
      <van-dropdown-item
        :value="value"
        :options="categories"
        @change="change"
      />
    </van-dropdown-menu>
  </div>
</template>

<script>
export default {
  props: {
    value: Number,
  },
  data() {
    return {
      categories: [
        { text: "全部课程", value: -1 },
        { text: "node", value: 0 },
        { text: "react", value: 1 },
        { text: "vue", value: 2 },
      ],
    };
  },
  methods: {
    change(newValue) {
      this.$emit("input", newValue);
    },
  },
};
</script>

<style lang="scss">
.home-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 48px;
  background: $background;
  padding: 0 20px;
  img {
    width: 30px;
    height: 30px;
  }
}
</style>
    1. home组件
// src/views/home/index.vue  父组件
<template>
  <div>
    <!-- v-model 相当于 :value="value" @input="change" -->
    <HomeHeader v-model="value"></HomeHeader>
  </div>
</template>

<script>
import HomeHeader from "./home-header";
export default {
  components: {
    HomeHeader,
  },
  data() {
    return {
      value: -1, // 全部 -1, node 0, react 1, vue 2
    };
  },
};
</script>

7. vuex模块状态分类

    1. 模块分类
新增文件夹和文件
src
  store
    modules
      home
        actions.js
        mutations.js
        state.js
      lesson
        state.js
      user
        state.js
// src/store/modules/home/actions.js
const homeActions = {
}
export default homeActions

// src/store/modules/home/mutations.js
const homeMutations = {
}
export default homeMutations

// src/store/modules/home/state.js
const homeState = {
  category: -1
}
export default homeState
    1. 模块集中处理导出
// src/store/modules/index.js

// webpack内置的
const files = require.context('.', true, /\.js$/)  // 第一个参数表示目录,第二个参数表示是否搜索子目录,第三个匹配正则

const modules = {}
files.keys().forEach(key => {
  const path = key.replace(/\.\/|\.js/g, '')  // 去掉 ./ 和 .js
  if (path === 'index') return  // 自己不做任何处理
  let [namespace, type] = path.split('/')
  if (!modules[namespace]) {
    modules[namespace] = {
      namespaced: true  // 都增加了命名空间
    }
  }
  // {home: { "namespace": true, "actions": {}, "mutations": {}, "state": {}}, user: {}}
  modules[namespace][type] = files(key).default  // 获取文件导出的结果
})
export default modules
    1. 公共管理
// src/store/index.js
import Vue from "vue";
import Vuex from "vuex";
import modules from './modules/index.js'

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {  // 公共的状态
  },
  mutations: {
  },
  actions: {},
  modules: {
    ...modules
  },
});
console.log(store.state)  // 验证
export default store

8. vuex中的状态管理

  • 问题:首页选择课程后,切换到我的课程页面,再返回,课程恢复到了默认状态。我们想返回时,依然是之前的状态。使用vuex管理状态
    1. 设置常量
// src/store/action-types.js
// 所有的名字都列在这里
export const SET_CATEGORY = 'SET_CATEGORY'
    1. 同步修改
// src/store/modules/home/mutations.js
import * as Types from '@/store/action-types'

const homeMutations = {
  [Types.SET_CATEGORY](state, payload) {  // 修改分类状态
    state.category = payload
  }
}
export default homeMutations
    1. 使用
// src/views/home/index.vue
<template>
  <div>
    <!-- v-model 相当于 :value="value" @input="change" -->
    <HomeHeader v-model="currentCategory"></HomeHeader>
  </div>
</template>

<script>
import HomeHeader from "./home-header.vue";
import { createNamespacedHelpers } from "vuex";
import * as Types from "@/store/action-types";

// 这里拿到的是 home 模块下的
let { mapState: mapHomeState, mapMutations } = createNamespacedHelpers("home");

export default {
  methods: {
    ...mapMutations([Types.SET_CATEGORY]),
  },
  computed: {
    ...mapHomeState(["category"]), // 获取vuex中的状态绑定到当前的实例
    currentCategory: {
      get() {
        // 取值
        return this.category;
      },
      set(value) {
        // 修改状态,默认会调用mutation更改状态
        this[Types.SET_CATEGORY](value);
      },
    },
  },
  components: {
    HomeHeader,
  },
  data() {
    return {
      value: -1, // 全部 -1, node 0, react 1, vue 2
    };
  },
};
</script>
    1. 验证
      选择不同的课程,切换底部导航页面,返回时状态依然保留
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容