前后端分离——前端vue开发笔记

一、报错找不到.vue

明明路径没错,因为同一文件夹下存在同名的index.vue/index.js/index.css文件,所以配置的查找顺序一定要对。
webpack.base.conf.js中配置:
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  }
默认先查找.js再找.vue再找.json文件,所以换一下顺序即可。
改为:extensions: ['.vue', '.js', '.json']

 

二、跨域问题的代理配置

/config/index.js中配置
proxyTable: {
  '/api/**': {
    target: 'http://10.10.17.63:8089/',
    changeOrigin: false,
    secure: false,
    pathRewrite: {
      '^/api': '/'
    }
  }
}
解释:
请求发送url,匹配/api的会代理到这里,目标地址是后台的IP+PORT。
pathRewrite的意思是将url中的/api替换为/即有如下效果。
目标访问后台接口:http://10.10.17.63:8089/loginUser
请求URL为:/api/loginUser,请求发送后会通过代理将目标路径拼接上并去掉拦截标识。
即将请求转发至http://10.10.17.63:8089/loginUser


三、fixed超出窗口大小部分无法滚动

问题:

使用fixed固定一个div,当这个div高度大于窗口高度后,超出的内容无法滚动查看。

解决办法:

在设置fixed的div添加样式 height:100%;overflow:auto; 即可。
据说还可以设置样式 max-height:100%;overflow:auto; 即可。
具体还是根据情况设置当前div的宽度,若当前div宽度是个固定值不想设置成百分数,则:
可以在外层包裹一个div设置为position:fixed;height:100%;overflow:auto;当前div就不需要在fixed,正常设置高宽等即可。

 

四、刷新或者加载出现变量闪烁再显示值的问题


v-cloak :用于解决初始化慢导致页面闪动的问题

对于简单的项目很实用,但是在工程化的项目中,项目的HTML文件只有一个空的div元素,剩余内容都是用路由挂在不同组件完成的,所以不需要v-cloak。

 

五、动画变换效果

问题1:transition有时有效有时无效

.submit:hover {
  color: #E0ECFF;
  transition: 2s all; // 有用!!
}
.submit:active {
  top: 30px;
  /* transition: 2s all; 没点用 */
}

结果:因为top变换没有初始值!!!

思考过程:hover和active互换没影响、transition:格式更改没变化、color和top互换发现问题top没用。是不是float的原因呢?但是已经是相对定位了应该没有关系。
所以对比两者差距,答案只有一个,top没有给初始值啊!晕。
建议规范的正确写法如下:
.submit {
  color: #ACE2F5;
  top: 0;
}
.submit:hover {
  color: #E0ECFF;
  transition: color 2s;
}

.submit:active {
  top: 30px;
  transition: top .2s;
}

问题2:animation过渡无效

.float-quit-show {
  animation: quitshow 1s forwards; /* 改变过度动画效果 */
}
@keyframes quitshow {
  0% {
    top: 0px;
    opacity: 0;
  }
  100% {
    bottom: 0px;
    opacity: 1;
  }
}

以上代码段,过度动画设置失败,因为从top到bottom是没有过度效果的!

改成如下,才有从上往下飞的效果:
@keyframes quitshow {
  0% {
    bottom: 50%;
    opacity: 0;
  }
  100% {
    bottom: 0px;
    opacity: 1;
  }
}

 

六、vue的生命周期

将路由导航、keep-alive、和组件生命周期钩子结合起来的,触发顺序,假设是从a组件离开,第一次进入b组件:

beforeRouteLeave:路由组件的组件离开路由前钩子,可取消路由离开。
beforeEach:路由全局前置守卫,可用于登录验证、全局路由loading等。
beforeEnter:路由独享守卫
beforeRouteEnter:路由组件的组件进入路由前钩子。
beforeResolve:路由全局解析守卫
afterEach:路由全局后置钩子
beforeCreate:组件生命周期,不能访问this。
created:组件生命周期,可以访问this,不能访问dom。
beforeMount:组件生命周期
deactivated:离开缓存组件a,或者触发a的beforeDestroy和destroyed组件销毁钩子。
mounted:访问/操作dom。
activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。
执行beforeRouteEnter回调函数next。

 

七、webpackage配置

productionSourceMap:false, // 打包完后才会看不到源码
open: config.dev.autoOpenBrowser, // 自动打开浏览器
openPage: 'login', // 自动打开浏览器到指定页面

 

八、动态路由加载

/* 无语routeArray[0].children.push(routeChild)就报错
[vue-router] "path" is required in a route configuration. */
routeArray[0].children = routeChild
但是后面换了一种写法又不报错了,费解

 

九、console.log打印的问题

其实有时候打印的不是当前值,点开可以看到有个感叹号提示value below was evaluated just now

 

十、边界叠加的问题

有时候去掉border:1px solid transparent;div会移动因为边界叠加的问题
还有一种情况设置font-size: 0px;

 

十一、ajax发HTTP请求时报错:

[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.
中文翻译:
在主线程同步XMLHttpRequest是不赞成的,因为对最终用户的体验有不利影响。
原因:
以上警告信息在ajax方法执行同步操作(等有了返回值才执行下面的js,会短暂阻断程序继续执行)的时候出现,即:async:false。
如果业务层面允许,推荐异步执行AJAX,即将async属性设置为true。(async缺省下为true)
如果非要使用同步的Ajax(这种情况应该很少见),HTML5中增加了Worker对象,每个Worker运行在一个独立的线程中,Worker线程被阻塞一般是不会影响主线程和浏览器的。

 

十二、overflow失效

所有的overflow失效,尤其是overflow-x失效,是因为当前层的宽度未设置。

 

十四、this.$confirm闪退的问题

 


downloadDoc () {
      this.$confirm('是否需要下载帮助文档?', '下载', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'info'
      })
        .then(() => {
          this.helpDocDownload()
          this.$message({
            type: 'success',
            message: '下载成功!'
          })
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消下载'
          })
        })
    }
初次点击a标签时,弹出框会闪退,再次点击正常。
因为href="#"会定位到页面顶部,即出现,点击弹出框外部导致弹出框退出关闭的效果。
将标签改为如下即可:

 

十五、const和let的区别

let声明的变量可以改变,值和类型都可以改变,没有限制。
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

 

十六、eslint启用和禁用

ESLint是一个代码规范和错误检查工具,局部禁用代码检查可将不检查部分代码夹在disable和enable之间,如下:
/* eslint-disable */
此区域内将不进行代码规范检查
/* eslint-enable */

 

十七、Vue.js devtool插件问题

报错:
Vue.js is detected on this page. Devtools inspection is not available because it's in production mode or explicitly disabled by the author.
1、刷新后打开开发者工具,没用。
2、更多工具-扩展程序-Vue.js devtools详细信息-允许访问文件网址打开,没用。
3、修改Users\***\AppData\Local\Google\Chrome\User Data\Default\Extensions\nhdogjmejiglipccpnnnanhbledajbpd\对应版本下的manifest.json文件,

"background": {
    "persistent": false,
    "scripts": [ "build/background.js" ]
}

"background": {
    "persistent": true,
    "scripts": [ "build/background.js" ]
}
没用。
4、检查是否使用的是vue.min.js,恍然意识到打开的是服务器上的web系统使用的vue.min.js,打开本地的系统vue.js devtool能正常使用!!

 

十八、forEach究竟能不能改变数组的值

因为forEach效率高选用forEach,结果发现无法修改数组的值,详见
https://blog.csdn.net/ZhengKehang/article/details/81281563

总结:
若原数组oldArr的元素是基本数据类型,则如下:
oldArr.forEach((el)=>{
    el = 2
})
是没法将数组oldArr中的每个值改成2的。
若一定要将原数组oldArr中的数值改为2,则可通过明确数组下标的方式修改,如下即可:
oldArr.forEach((el,index)=>{
    oldArr[index] =2
})

 

十九、定时器的问题

原来有个定时器,这么写:
function MapInit (flag) {
  pageFlag = flag
  svgDoc = null
  if (svgDoc === null) {
    clearTimeout(timeSvgDoc)
    console.log(111)
    timeSvgDoc = setTimeout(MapInit(1), 1000)
  } else {
    ……
  }
}
结果:控制台飞速打印111,直达栈溢出
思考:
1、怀疑有多个定时器存在,于是加上clearTimeout(timeSvgDoc),没用。
2、考虑修改时间间隔,1000改为10000即10s钟,发现没用任何影响,飞速打印111。
3、对比其他正常的定时器,发现写法不对,改为如下即可。
function MapInit (flag) {
  pageFlag = flag
  svgDoc = null
  if (svgDoc === null) {
    clearTimeout(timeSvgDoc)
    timeSvgDoc = setTimeout(() => {
      MapInit(1)
    }, 1000)
  } else {
    ……
  }
}
原因:
问题在于定时器setTimeout的第一个参数要求是一个函数,比如
setTimeout(MapInit,1000)
但是因为函数带了参数时,第一个参数其实是函数的返回值了,如下:
setTimeout(MapInit(1),1000)
所以马上执行了MapInit函数获取其返回值,而返回值定时1s后执行并没有什么效果。

 

二十、JS浮点数运算的误差问题

经典问题:
0.1 + 0.2 === 0.3 // false
同样的系统中碰到:
30-19.47=10.530000000000001
问题原因:
因为浮点数运算的时候,先转化为二进制,用二进制来算,结果再转回十进制。
而浮点数19.47转化为二进制是个无限循环小数,只能取近似值,误差就这么产生了。
解决办法:
用toFixed()四舍五入为指定的小数位数即可。

 

二十一、$route和$router的区别和使用

$route是一个对象,当前路由对象,从中可以获取name、path、query、params等
$router是VueRouter的一个实例对象,可调用其中的push、replace、go等方法进行路由跳转
因为main.js中有:
import router from './route'
new Vue({
  el: '#app',
  router,
  template: '',
  components: { App }
})
所以对于.vue来说已经全局导入了router,在对应的js就无需再次import router from '../../route',只需使用this.$router.push()等路由跳转方法即可。
而对于其他js文件,因为没有this.$router对象,所以需要从外部导入import router from '../../route',然后使用router.push()等路由跳转方法即可。

 

二十二、Vue在IE下显示空白问题

现象:
IE打开vue写的前端项目,一片空白,控制台报错“Promise未定义”或报错[vuex] vuex equires a Promise polyfill in this browser.
原因:
主要是IE对Promise支持不友好,对ES6新语法不支持。
解决步骤:
1、安装 npm install --save babel-polyfill
2、在package.json中添加依赖,
devDependencies:{
    "babel-polyfill": "^6.22.0"
}
3、在main.js中添加引用import 'babel-polyfill'
4、在webpack.base.config.js文件中修改,往app数组添加'babel-polyfill'
module.exports = {
     entry: {
     app: ['babel-polyfill', './src/main.js']
     }
}
拓展:
最新ES 语法:比如,箭头函数
最新ES API:比如,Promise
最新ES 实例方法:比如,String.includes

 

二十三、容易混淆的样式选择器

.class1 .class2 {
    class1的子元素、孙子元素含有class2的
}
.class1.class2 {
    同时有class1 class2的元素节点
}
.class1 > .class2 {
    class1的子元素含有class2的
}

 

二十四、typeof和instanceof的一个问题

判断对象类型时经常出现如下问题
typeof aaa // "string"
aaa instanceof String // false
为什么?怎么办?

首先了解一下typeof和instanceof分别是什么:
typeof
此操作符返回一个字符串,表示未经计算的操作数的类型。
下表总结了typeof常见的返回值
前后端分离——前端vue开发笔记_第1张图片
等,详见https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof
额外的,我们可以巧用typeof来判断一个变量是否存在,用typeof a !== "undefined"代替if(a)更好,因为如果a为定义if(a)会报错。
instanceof
该运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置,oops有点听不太懂。
详见https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof里面有提到String对象的一些特殊情况
var simpleStr = "This is a simple string";
simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined
这不就回答了我常遇见的问题!!

然后,分析如下:
simpleStr和aaa一样,只是一个以string为数据类型的值,并不是String的实例对象。
aaa instanceof String 在只有左侧是右侧类的对象时才会返回ture
aaa instanceof Object 的结果同样是false(所有对象都是Object的实例)
也就是说aaa本身并不是任何一个类的实例,如图

前后端分离——前端vue开发笔记_第2张图片

若将这个数据类型转换为String的类对象就会出现如下情况:
var bbb = new String(aaa);
bbb instanceof String //ture

最后可改为如下判断:
typeof aaa // "string"
aaa instanceof String // false
typeof aaa === 'string' // true

 

二十五、文件存放static或assets

关于文件存放static还是assets下,看了很多说明后我自己的理解就是:
static下的不会编译直接复制过去,assets下的文件会进行编译。编译感觉能起到一定的“加密”作用??
那么如果是外部引用文件就放在static,自己的文件还是放到assets吧。
但是我为了方便管理统统放到static下了,各位置引入static下的文件写法:
js中必须以相对路径:                     ../../../../static/json/***.json
css中绝对路径必须以/开始:          background: url(/static/img/***.png);
html标签中绝对路径可以省去/:     或者

 

二十六、div的层叠关系注意点

1、默认后面的div会覆盖在前面的div上
2、如果1不是那么会事,有可能是div的position不对,父设置为绝对位置,子设置为相对位置,好像不要设置为静态都可以。
3、通过z-index调整,数字越大优先级越高,越在上层

 

二十七、v-model绑定数据无法触发状态更新

官方文档 https://cn.vuejs.org/v2/guide/list.html#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9 有提到
“数组更新检测”部分的注意事项写明了:由于 JavaScript 的限制,Vue 不能检测以下变动的数组。
1、当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
2、当你修改数组的长度时,例如:vm.items.length = newLength

正巧我就碰到1所述的情况:

let arrayList = [
	{
		code: 'a',
		val: 'aaa'
	},
	{
		code: 'b',
		val: 'bbb'
	}
]
for (let i = 0; i < arrayList.length; i++) {
	let code = arrayList[i].code
	let val = arrayList[i].val
	this.buildData[code] = val
}

明明console(this.buildData)出来buildData是有值的,但是v-model绑定的{{buildData['a']}}却显示空白。

参照官方提供的解决办法如下:

方法一:
通过 vm.$set 实例方法依次循环赋值,

this.buildData[code] = val

this.$set(this.buildData, code, val)

方法二:
通过 splice 函数依次循环赋值,

this.buildData[code] = val

this.buildData.splice(code, 1, val)

方法三:
我发现在循环完成后直接调用vm.$set也可触发buildData状态更新,即
for (let i = 0; i < arrayList.length; i++) {
    let code = arrayList[i].code
    let val = arrayList[i].val
    this.buildData[code] = val
}
this.$set(this.rawData)

方法四:
经尝试,在循环赋值开始前将buildData置空也可以触发其状态更新,即
this.buildData = {}
for (let i = 0; i < arrayList.length; i++) {
    let code = arrayList[i].code
    let val = arrayList[i].val
    this.buildData[code] = val
}

 

二十八、网络问题影响前端访问时

正常访问页面,然后网络连接断开或者IP变化,仍然能切换页面,只是加载不了数据,思考可能有两个原因:
1、浏览器缓存
2、浏览器已加载所有文件到本地
尝试清空缓存,重新登录后断网,再切换路由是没法切换的。
原因是使用了路由懒加载,且没有缓存的时候,是无法切换路由的。
懒加载:const Foo = () => Promise.resolve({ /* 组件定义对象 */ })
若使用直接导入,webpack会把所有的路由指向包一起加载到本地文件。
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')

 

二十九、冒号绑定值的问题

在vue中绑定属性值时,比如

1、若title前不加冒号:

会被当做html文本处理成字符串,也就是title最终渲染出来是字符串"dialogTitle"

2、若title前加冒号:

会被当做模板处理,在渲染的时候会进行相应的填值处理。

所以
当dialogTitle处为数值、布尔值时,必须要在title前加上冒号,比如:


否则会被当成字符串true和字符串101。

你可能感兴趣的:(vue)