项目部署遇到的那些坑
页面URL中“#”的处理;
使用vue-cli生成的项目模板,运行时在url地址栏多了一个“#”号,服务器部署后会出现“http://localhost:80/#/”的情况;
解决方案:修改“src/router/index.js"文件,修改 vue-router 模式为history,设置bashurl效果正常了
2. 服务器部署 vue 子模块项目
有一个项目地址为http://localhost:80/,这个项目下又添加了一个子模块,子模块是单独的一个项目,域名效果变成http://localhost:80/sk的形式访问子模块项目的首页,通过http://localhost:80/sk/home的方式访问子模块项目路由页面
解决方案:
第一步:修改src/router/index.js文件中 router 的bash配置,效果如下
Vue.use(Router)exportdefaultnewRouter({mode:'history',base:'/sk',routes:[{path:'/',name:'home',component:home}]})
第二步:修改npm run build命令打包生成的目录结构。打开前端项目根目录下/config/index.js文件,打包的默认路径为生成dist静态文件目录,默认路径配置如下
...build:{index:path.resolve(__dirname,'../dist/index.html'),assetsRoot:path.resolve(__dirname,'../dist'),assetsSubDirectory:'static',assetsPublicPath:'/',...
修改打包路径配置,静态文件目录下添加一个sk子目录,其他打包文件放到sk目录下,注意目录中的/, 前端项目中的配置完成了
...build:{index:path.resolve(__dirname,'../dist/sk/index.html'),assetsRoot:path.resolve(__dirname,'../dist/sk'),assetsSubDirectory:'static',assetsPublicPath:'/sk/',...
第三步:修改dev属性下的assetsPublicPath路径配置,由原来的/修改为/sk/
...dev:{// PathsassetsSubDirectory:'static',assetsPublicPath:'/sk/',proxyTable:{},// Various Dev Server settingshost:'localhost',// can be overwritten by process.env.HOSTport:8080,// can be overwritten by process.env.PORT, if port is in use, a free one will be determinedautoOpenBrowser:false,...
第四步:修改服务器 nginx 的配置,设置sk路径访问内容,配置如下
...server{listen80;server_name example.com;location /{try_files$uri/index.html;root /xxx/projects/example/frontend/dist;}location /sk{try_files$uri/sk/index.html;alias/xxx/projects/example-sk/frontend/dist/sk;}}...
项目开发中遇到的那些坑
父组件引用子组件
第一步:引入子组件:
import StateWatchListPage from '子组件的路径';
第二步:将子组件名称加入到components对象
components:{ StateWatchListPage }
第三步:使用子组件
2. 路由变化页面数据不刷新问题:
出现这种情况是因为依赖路由的params参数获取写在created生命周期里面,因为路由懒加载的关系,退出页面再进入另一个文章页面并不会运行created组件生命周期,导致文章数据还是第一次进入的数据
解决方法:watch监听路由是否变化
watch: { // 方法1 '$route' (to, from) { //监听路由是否变化 if(this.$route.params.articleId){// 判断条件1 判断传递值的变化 //获取文章数据 } } //方法2 '$route'(to, from) { if (to.path == "/page") { /// 判断条件2 监听路由名 监听你从什么路由跳转过来的 this.message = this.$route.query.msg } }}
3. 异步回调函数中使用this无法指向vue实例对象
//setTimeout/setInterval ajax Promise等等data(){ return{ ... }},methods (){ setTimeout(function () { //其它几种情况相同 console.log(this);//此时this指向并不是vue实例 导致操作的一些ma'f },1000);}
解决方案:使用变量赋值或是箭头函数
//使用变量访问this实例let self=this; setTimeout(function () { console.log(self);//使用self变量访问this实例 },1000); //箭头函数访问this实例 因为箭头函数本身没有绑定this setTimeout(() => { console.log(this); }, 500);
插播:ES6中var和let的区别
通过var定义的变量,作用域是整个封闭函数,是全域的 。通过let定义的变量,作用域是在块级或是子块中
for (let i = 0; i < 10; i++) {// ... }console.log(i); // ReferenceError: i is not defined //计数器i只在for循环体内有效,在循环体外引用就会报错。
变量提升现象:浏览器在运行代码之前会进行预解析,首先解析函数声明,定义变量,解析完之后再对函数、变量进行运行、赋值等。
-不论var声明的变量处于当前作用域的第几行,都会提升到作用域的头部。
-var 声明的变量会被提升到作用域的顶部并初始化为undefined,而let声明的变量在作用域的顶部未被初始化
// var 的情况 console.log(foo);// 输出undefinedvar foo =2; //相当于var foo; //声明且初始化为undefined console.log(foo); foo=2;// let 的情况 console.log(bar); // 报错ReferenceErrorlet bar = 2; //相当于在第一行先声明bar但没有初始化,直到赋值时才初始化
但是直接用let声明变量不赋值是会打印undefined,还是初始化了,只是let声明放在赋值之后,let声明会提前但不会初始化。
let a; alert(a);//值为undefined alert b;//会报错let b;
只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的,尽管代码块外也存在相同全局变量。
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceErrorlet tmp; } alert(tmp); //输出值为123,全局tmp与局部tmp不影响
let不允许在相同作用域内,重复声明同一个变量。
// 报错function() {let a = 10; var a = 1; } // 报错function() {let a = 10; let a = 1; }
4. setInterval路由跳转继续运行并没有及时进行销毁
一些弹幕,走马灯文字,这类需要定时调用的,路由跳转之后,因为组件已经销毁了,但是setInterval还没有销毁,还在继续后台调用,控制台会不断报错,如果运算量大的话,无法及时清除,会导致严重的页面卡顿。
解决办法:在组件生命周期beforeDestroy停止setInterval
//组件销毁前执行的钩子函数,跟其他生命周期钩子函数的用法相同。beforeDestroy(){ //我通常是把setInterval()定时器赋值给this实例,然后就可以像下面这么停止。 clearInterval(this.intervalId);},
5. 实现vue路由拦截浏览器的需求,进行一系列操作 草稿保存等等
场景:为了防止用户失误点错关闭按钮等等,导致没有保存已输入的信息(关键信息)。
解决办法:
//监听当前页面返回事件 beforeRouteLeave(to, from, next) { //next方法传true或者不传为默认历史返回,传false为不执行历史回退if(this.backStatu){next(true);}else{next(false);}this.tipshow = true; },
网友评论