2020-12-09 | 项目构建 | UNLOCK | 更新时间:2023-1-9 17:32

Vue2 项目的开始和扩展问题

Vue 是渐进式框架,它的数据是响应式的,基于数据是可变的,数据双向绑定,通过watch对属性进行监听,Vue通过数据劫持结合发布订阅者模式来实现数据双向绑定,它遍历data中的所有属性,通过Object.defineProperty 来劫持各个属性的 setter和getter,在数据变动时,以Dep算法遍历所有订阅者,发布消息触发回调,完成视图更新。

使用须知

文中举例,默认 yarn 和 @vue/cli 是已经安装了,如果没有安装,请先运行以下命令安装后;

npm install yarn -g
npm install @vue/cli -g || yarn add global add @vue/cli

开启项目

vue create xxx
cd xxx
yarn add vue-router
yarn add vuex
yarn add es6-promise //可选,兼容低版本IE

示例代码

入口文件 main.js
import 'es6-promise/auto' //引入低版本兼容polyfill import Vue from 'vue' //引入vue import router from './Router' //对路由的放在一个文件里 import store from './vuex' //将vuex放在一个文件里管理 Vue.config.productionTip=false //阻止vue启动生产消息 const App=()=><router-view></router-view> //显示的是当前路由渲染的界面 new Vue({ render: h=>h(App), //render方法渲染 router, store }).$mount('#app')
路由集合 Router.js
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) // 组件 import Home from './components/Home.vue' import Hello from './components/Hello.vue' import Word from './components/Word.vue' import Nofined from './components/Nofined' const routes=[ {path:'/',component:Home}, {path:'/hello',component:Hello, //嵌套路由 children:[ {path:'word',component:Word}, ] }, {path:"*",component:Nofined} //404页面 ] const router=new VueRouter({ routes }) // 转跳滚动条初始化 router.beforeEach((to, from, next) => { document.body.scrollTop = 0 document.documentElement.scrollTop = 0 window.scrollTo(0, 0) next() }) export default router
状态管理 vuex.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const moduleA = { // modulle管理 state:{}, getters:{}, mutations:{}, actions:{}, } const store = new Vuex.Store({ //以 Vuex.Store 方法创建实例 state:{ //状态 name:"战争", }, getters:{ //计算 newName:state=>{ state.name=="1"?return '21':return '11'; } }, mutations:{//事件 commit newName(state,data){ //设置名称 state.name=data } }, actions:{ //行为 dispatch newName:function(context,data){ context.commit('newName',data) } }, modules:{ one:moduleA } }) export default store

相关扩展

在项目中配置模块的相关目录

src/
 |——api/ (所有请求:用户相关,功能相关等)
   |——user.js 
 |——assets/ (静态资源:图片,视频,字体等)
   |——images/ 
 |——components/ (所有组件:主页,登录,注册等)
   |——Home.vue
 |——config/ (所有配置项:网关,路由字体大小等)
   |——geteway.js
   |——router.js
 |——store/  (Vuex的数据中心)
   |——index.js
 |——utils/  (工具集合:请求,常用函数等)
   |——require.js
 min.js

在手机端设置区分前进后退的代码

路由集合 Router.js
//区分前进后退,主要是为了在移动端添加不同的动画 Vue.prototype.push = function(url){ //路由前进 let old=this.$router.currentRoute.path if(old==url){ this.$router.go(0); }else{ Vue.prototype.transitionName = "slide-left"; //通过设置不同的class触发动画 this.$router.push(url); } }; Vue.prototype.pop = function(n=-1){ //路由后退 Vue.prototype.transitionName = "slide-right"; let path = this.$router.currentRoute.path; if (path == "/") { return;} this.$router.go(n); }

在本地项目中配置proxy解决跨域请求

这是 vue-cli工具的配置,在项目的根目录创建 vue.config.js

vue.config.js
module.exports = { devServer: { //请求配置 proxy: { "/user": { //将路径匹配为 /user 的请求转发到该路径 target: 'https://uat.happit.cn/', //转发路径 changeOrigin:true }, "/api":{ target: 'http://112.126.99.105:8010/', changeOrigin:true, pathRewrite:{ //重写路径,将所有api重写为空 '^/api':'' } }, } } }

在项目中配置接口请求和数据异步处理

yarn add axios
yarn add vue-axios

main.js 入口文件
import Vue from 'vue' import axios from 'axios' import vueAxios from 'vue-axios' Vue.use(vueAxios,axios)
/require.js
import Vue from 'vue' import axios from 'axios' //请求拦截器 axios.interceptors.request.use(function (config) { //添加身份验证 // if(config.headers.Authorization === undefined) { // config.headers.Authorization = 'Bearer ' + store.state.token // } return config; }, function (error) { console.log(error) return Promise.reject(error); }); function require(option){ return new Promise((fulfill,reject)=>{ Vue.axios(option).then((res)=>{ fulfill(res) }).catch((rej)=>{ if(rej.response){ reject(rej.response) }else if(rej.require){ reject(rej.require) }else{ reject(rej.message) } }) }) } export default require;
/config/geteway.js
// export const network='https://api.ixiaowai.cn' export const network='' //通过vue-cli设置服务器代理,在上线前需要改正 export const auto='api'
vue.config.js
module.exports={ devServer:{ proxy:{ "/api":{ target: 'https://api.ixiaowai.cn/', changeOrigin:true, pathRewrite:{ //重写请求路径,将api标记清除 '^/api':'' } }, } } }
/api/other.js
import requires from '@/utils/require' import {network,auto} from '@/config/geteway' export const saying=function(params){ //接口请求 return require({ url:`${network}/${auto}/ylapi.php`, method:'GET', params }) }

生产代码上路由按需加载

基于vue-cli

// 通过路由切割
const Home=()=>import('@/components/Home.vue')
const routers=[
  {path:'/',component:Home},  //在通过路由进行引用,就可以对路由进行切割
]

// 通过异步组件切割:使用 import按需加载的方式也可以进行切割,但如果网络不好就会空白一片,
// 所以需要显示加载中的话就需要用到异步组件的方式
const AsyncComponent = () => ({
  component: import('@/MyComponent.vue'), // 需要加载的组件 (应该是一个 `Promise` 对象)
  loading: LoadingComponent, // 异步组件加载时使用的组件
  error: ErrorComponent, // 加载失败时使用的组件
  delay: 200, // 展示加载时组件的延时时间。默认值是 200 (毫秒)
  timeout: 3000   // 超时时间和组件加载都超时, 则使用加载失败时使用的组件。默认值是:`Infinity`
})

设置生产打包路径

默认打包路径为根目录,所有需要设置 assetsPublicPath./ 当前路径

vue.config.js
module.exports = defineConfig({ //... publicPath:"./", })

部分页面或组件进行缓存处理

通过 keep-alive 包裹组件,会缓存不活动的路由。

App.vue
<!-- include 表示符合该正则的路由组件会缓存 --> <keep-alive> <router-view v-if="$route.meta.keepAlive"/> </keep-alive> <router-view v-if="!$route.meta.keepAlive"/>
router.js
{ path: '/account', name: 'Account', meta: {keepAlive: true}, // 通过路由的meta参数进行缓存配置 component: () => import('../views/account') }

问题

Uncaught TypeError: Cannot read properties of undefined (reading ‘install‘)报错,页面全空白

vue-router的版本问题,vue-router4区别于3 ,没有了默认导出export default的模块,需要使用 import {createrRouter} from ‘vue-router’的方式进行导入;之后在页面引用<router-view>的时候同样需要进行模块引入;vue.use();建议将vue-router 替换成 3.1.3版本;

在Vue 中 import 引入的路径中的 @ 指代什么?

import require from '@/utils/require'

在Vue中,@ 是指代 /src 目录,是为了防止复杂路径导致的出错;

请求报错 No ‘Access-Control-Allow-Origin’?

该错误很大可能是属于请求跨域报错,需要使用vue-cli设置代理,在根目录创建 vue.config.js

```js vue.config.js
module.exports={
devServer:{
proxy:{
‘user/‘:{
target:”https:xxxx”,
changeOrigin:true,
}
}
}
}

Vue