【vue】常见开发知识点与问题整理(持续更新)

vue

1.vue双向数据绑定vuex中的state

在vue中, 不允许直接绑定vuex的值到组件中, 若是直接使用, 则会报错 have no setter

方法一: 使用get和set

// 在从组件的computed中

computed: {

user: {

get() {

return this.$store.state.user

},

set(v) {

// 使用vuex中的mutations中定义好的方法来改变

this.$store.commit(\'USER\', v)

}

}

}

// 在组件中就可以使用

<input v-modle="user" />

方法二: 使用watch

// 在组件中绑定

<input v-modle="user" />

// 在computed中获取vuex的值

computed: {

...mapState( { user: state => state.user } )

}

// 在组件的watch中观测

watch: {

\'user\': {

deep: true,

handler(value) {

// 使用vuex中的mutations中定义好的方法来改变

this.$store.commit(\'USER\', value)

}

}

}

 2.(webpack)vue-cli构建的项目如何设置每个页面的title

在路由里每个都添加一个meta:

[{

path:\'/login\',

meta: {

title: \'登录页面\'

},

component:\'login\'

}]

钩子函数,在main.js中添加如下代码:

router.beforeEach((to, from, next) => {

window.document.title = to.meta.title;

next()

})

3.vue项目中使用axios上传图片等文件

通过form表单提交,html代码如下:

<input name="file" type="file" accept="image/png,image/gif,image/jpeg" @change="update"/>

JS代码:

import axios from \'axios\'

update(e) {

let file = e.target.files[0]

let param = new FormData(); // 创建form对象

param.append(\'file\', file); // 通过append向form对象添加数据

param.append(\'chunk\', \'0\'); // 添加form表单中其他数据

let config = { // 添加请求头

headers: {

\'Content-Type\': \'multipart/form-data\'

}

};

axios.post(\'http://172.19.26.60:8080/user/headurl\', param, config)

.then(response => {

if (response.data.code === 200) {

this.ImgUrl = response.data.data;

}

})

}

 4.qs.stringify() 和JSON.stringify()的区别、vux中使用post提交表单数据需要qs库序列化

qs库的npm地址:https://www.npmjs.com/package/qs

功能虽然都是序列化。假设我要提交的数据如下:

var a = {name:\'hehe\',age:10};

qs.stringify序列化结果如下:name=hehe&age=10

而JSON.stringify序列化结果如下:"{"a":"hehe","age":10}"

vux中使用post提交表单数据:

this.$http.post(this.$sign.config.url.loginUrl,this.$qs.stringify({

"phone":this.phoneNumber,

"vCode":this.loginCode,

"smsCode":this.phoneCode

})

)

.then(response=>{

console.log(response.data);

if(response.data.httpCode == 200){

}else{

}

})

在firebug中可以看到传递的参数:phone=15210275239&vCode=8vsd&smsCode=1534

在vue中使用axios:

this.$axios.post(loginUrl, {

"email": this.email,

"password": this.password

}, {

transformRequest: (data) => {

return this.$qs.stringify(data)

},

}).then(res => {

if(res.data.resultCode == RESULT_CODE_SUCCESS){

console.log(\'登录成功\');

this.$router.push({name:"home"})

}else{

console.log(\'登录失败\');

}

}).catch(err => {

console.log(\'登登录出现错误\');

})

 5.vue全局实现的setCookie、getCookie、delCookie

//设置cookie,增加到vue实例方便全局调用

Vue.prototype.setCookie = (c_name, value, expiredays) => {

var exdate = new Date();    

exdate.setDate(exdate.getDate() + expiredays);    

document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());

}

//获取cookie

Vue.prototype.getCookie = (name) => {

var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");

if (arr = document.cookie.match(reg)){

return (arr[2]);

}

return null;

}

//删除cookie

Vue.prototype.delCookie =(name) => {

var exp = new Date();

exp.setTime(exp.getTime() - 1);

var cval = this.getCookie(name);

if (cval != null){

document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();

}

}

 6.webpack proxyTable 代理跨域

webpack 开发环境可以使用proxyTable 来代理跨域,生产环境的话可以根据各自的服务器进行配置代理跨域就行了。在我们的项目config/index.js 文件下可以看到有一个proxyTable的属性,我们对其简单的改写:

proxyTable: {

\'/api\': {

target: \'http://api.douban.com/v2\',

changeOrigin: true,

pathRewrite: {

\'^/api\': \'\'

}

}

}

这样当我们访问localhost:8080/api/movie的时候 其实我们访问的是http://api.douban.com/v2/movie这样便达到了一种跨域请求的方案。

当然我们也可以根据具体的接口的后缀来匹配代理,如后缀为.shtml,代码如下:

proxyTable: {

\'**/*.shtml\': {

target: \'http://192.168.198.111:8080/abc\',

changeOrigin: true

}

}

可参考地址:

  • webpack 前后端分离开发接口调试解决方案,proxyTable解决方案
  • http-proxy-middleware

 7.vue和mintui-Loadmore结合实现下拉刷新,上拉加载 (待优化)

mintui是饿了么团队针对vue开发的移动端组件库,方便实现移动端的一些功能,这里只用了Loadmore功能实现移动端的上拉分页刷新,下拉加载数据.
mintui官网:http://mint-ui.github.io/#!/zh-cn

<template>  

<div class="main-body" :style="{\'-webkit-overflow-scrolling\': scrollMode}">

<v-loadmore :top-method="loadTop" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded" :auto-fill="false" ref="loadmore">

<ul class="list" v-for="(val, key) in pageList">

<li>

<div>我是小11</div>

<div>我是小11</div>

</li>

</ul>

</v-loadmore>

</div>

</template>

<script>

import {Loadmore} from \'mint-ui\';

export default {

data:function() {

return {

searchCondition:{ //分页属性

pageNo:"1",

pageSize:"10"

},

pageList:[],

allLoaded: false, //是否可以上拉属性,false可以上拉,true为禁止上拉,就是不让往上划加载数据了

scrollMode:"auto" //移动端弹性滚动效果,touch为弹性滚动,auto是非弹性滚动

}

},

components: {

\'v-loadmore\':Loadmore // 为组件起别名,vue转换template标签时不会区分大小写,例如:loadMore这种标签转换完就会变成loadmore,容易出现一些匹配问题

// 推荐应用组件时用a-b形式起名

},

mounted(){

this.loadPageList(); //初次访问查询列表

},

methods: {

loadTop:function() { //组件提供的下拉触发方法

//下拉加载

this.loadPageList();

this.$refs.loadmore.onTopLoaded();// 固定方法,查询完要调用一次,用于重新定位

},

loadBottom:function() {

// 上拉加载

this.more();// 上拉触发的分页查询

this.$refs.loadmore.onBottomLoaded();// 固定方法,查询完要调用一次,用于重新定位

},

loadPageList:function (){

// 查询数据

this.api.PageList(this.searchCondition).then(data =>{

// 是否还有下一页,加个方法判断,没有下一页要禁止上拉

this.isHaveMore(data.result.haveMore);

this.pageList = data.result.pageList;

this.$nextTick(function () {

// 原意是DOM更新循环结束时调用延迟回调函数,大意就是DOM元素在因为某些原因要进行修改就在这里写,要在修改某些数据后才能写,

// 这里之所以加是因为有个坑,iphone在使用-webkit-overflow-scrolling属性,就是移动端弹性滚动效果时会屏蔽loadmore的上拉加载效果,

// 花了好久才解决这个问题,就是用这个函数,意思就是先设置属性为auto,正常滑动,加载完数据后改成弹性滑动,安卓没有这个问题,移动端弹性滑动体验会更好

this.scrollMode = "touch";

});

});

},

more:function (){

// 分页查询

this.searchCondition.pageNo = parseInt(this.searchCondition.pageNo) + 1;

this.api.loadPageList(this.searchCondition).then(data=>{

this.pageList = this.pageList.concat(data.result.pageList);

this.isHaveMore(data.result.haveMore);

});

},

isHaveMore:function(isHaveMore){

// 是否还有下一页,如果没有就禁止上拉刷新

this.allLoaded = true; //true是禁止上拉加载

if(isHaveMore){

this.allLoaded = false;

}

}

}

}

</script>

PS:有个坑一定要注意就是注释里说的iPhone里loadmore和-webkit-overflow-scrolling属性冲突无法上拉问题

可参考另外一个插件,没有使用过,《简单灵活且强大的Vue下拉刷新组件:vue-pull-to》

8.vue非父子组件通信

如果2个组件不是父子组件那么如何通信呢?这时可以通过eventHub来实现通信。所谓eventHub就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。

方式一
组件1触发:

<div @click="eve"></div>

methods: {

eve() {

Hub.$emit(\'change\',\'hehe\'); //Hub触发事件

}

}

组件2接收:

created() {

Hub.$on(\'change\', (msg) => { //Hub接收事件

this.msg = msg;

});

}

 可参考:vue非父子组件怎么进行通信

方式二

把中转站数据存放到根实例下面,如下:

// 根组件(this.$root)

new Vue({

el: \'#app\',

router,

render: h => h(App),

data: {

// 空的实例放到根组件下,所有的子组件都能调用

Bus: new Vue()

}

})

组件1触发:

<div @click="eve"></div>

methods: {

eve() {

this.$root.Bus.$emit(\'change\',\'hehe\');

}

}

组件2接收:

created() {

this.$root.Bus.$on(\'change\', (msg) => { //接收事件

this.msg = msg;

});

}

注:官方推荐的eventbus 解决方案的缺陷在于, 在数据传递过程中,两个组件必须都已经被渲染过。

 9.IE9报vuex requires a Promise polyfill in this browser问题解决

因为使用了 ES6 中用来传递异步消息的的Promise,而IE低版本的浏览器不支持。

解决方法
第一步: 安装 babel-polyfill 

babel-polyfill可以模拟ES6使用的环境,可以使用ES6的所有新方法

npm install --save-dev babel-polyfill

第二步: 在 Webpack/Browserify/Node中使用

在webpack.config.js文件中把

module.exports = {

entry: {

app: \'./src/main.js\'

}

}

替换为:

module.exports = {

entry: {

app: ["babel-polyfill", "./src/main.js"]

}

};

当然还有其它两种引入方式:

  • require("babel-polyfill");
  • import "babel-polyfill";

10.启动Vue项目时提示: [BABEL] ... max of "500KB".

在项目的根目录下找到 .babelrc 文件,增加 "compact": false ,如:

{

"compact": false,

"presets": ["env", "react", "stage-0"],

"plugins": [

"transform-runtime"

]

}

如果不存在则手动创建该文件,并填写内容如:

{

"compact": false

}

 11.在main.js中监听微信浏览器返回按钮,让其不能返回

if(from.name == \'staffInfo\' && to.name == \'Login\'){

next({path:\'/staffInfo\',query:{redirect:from.fullPath}});

}else if(from.name == \'acountFill\' && to.name == \'Login\'){

next({path:\'/acount/acountFill\',query:{redirect:from.fullPath}});

}

12.pdf.js默认不显示电子签章(数字签名)问题解决

1. pdfjs 旧版本
pdf.worker.js 找到

if(this.data.fieldType === \'Sig\') {

warn(\'unimplemented annotation type: Widget signature\');

return false;

}

注解上面代码.
2. pdfjs 新 版本v1.10.88
pdf.worker.js 找到

if(data.fieldType === \'Sig\') {

_this2.setFlags(_util.AnnotationFlag.HIDDEN);

}

13.pdf.js预览,中文显示乱码解决方法

有可能是有pdf不支持的字体格式,引入pdf.js的字体试试

const CMAP_URL = \'https://unpkg.com/pdfjs-dist@2.0.489/cmaps/\';

pdfjsLib.getDocument({

data: pdfData,

cMapUrl: CMAP_URL,

cMapPacked: true,

})

14.解决Vue引入百度地图JSSDK:BMap is undefined 问题

export default {

init: function (){

//console.log("初始化百度地图脚本...");

const AK = "AK密钥";

const BMap_URL = "https://api.map.baidu.com/api?v=2.0&ak="+ AK +"&s=1&callback=onBMapCallback";

return new Promise((resolve, reject) => {

// 如果已加载直接返回

if(typeof BMap !== "undefined") {

resolve(BMap);

return true;

}

// 百度地图异步加载回调处理

window.onBMapCallback = function () {

console.log("百度地图脚本初始化成功...");

resolve(BMap);

};

// 插入script脚本

let scriptNode = document.createElement("script");

scriptNode.setAttribute("type", "text/javascript");

scriptNode.setAttribute("src", BMap_URL);

document.body.appendChild(scriptNode);

});

}

}

说明:

  • 直接使用官网提供的引用地址:http://api.map.baidu.com/api?v=2.0&ak=您的密钥
  • 启用 callback 参数,异步加载必须使用此参数才可以生效
  • 启用 https 配置,通过 s=1 参数实现
  • API版本为2.0,经测试使用,发现3.0版本在HTTPS环境下是有问题的,脚本内部某些请求固定使用HTTP,无法正常使用。

参考地址:https://segmentfault.com/a/1190000012815739

15.本地启动vue项目,host配置域名访问出现Invalid Host header 服务器域名访问出现的问题

在webpack.dev.config.js中找到 devServer下的hot,再下面添加 disableHostCheck: true,来解决127.0.0.1指向其他域名时出现"Invalid Host header"问题

如图所示:

16.vue项目中在使用vue-router切换页面的时候滚动条怎样自动滚动到顶部?

有时候我们需要页面滚动条滚动到某一固定的位置,一般使用Window scrollTo() 方法。

语法就是:scrollTo(xpos,ypos)

xpos:必需。要在窗口文档显示区左上角显示的文档的 x 坐标。

ypos:必需。要在窗口文档显示区左上角显示的文档的 y 坐标。

例如滚动内容的坐标位置100,500:

window.scrollTo(100,500);

好了,这个scrollTop这儿只是简单介绍一下,下面我们介绍下veu-router中的滚动行为。

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

注意: 这个功能只在 HTML5 history 模式下可用。

当创建一个 Router 实例,你可以提供一个 scrollBehavior 方法:

const router = new VueRouter({

routes: [...],

scrollBehavior (to, from, savedPosition) {

// return 期望滚动到哪个的位置

}

})

scrollBehavior 方法接收 to 和 from 路由对象。第三个参数 savedPosition 当且仅当 popstate 导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。

这个方法返回滚动位置的对象信息,长这样:

  • { x: number, y: number }
  • { selector: string, offset? : { x: number, y: number }} (offset 只在 2.6.0+ 支持)

如果返回一个 falsy (译者注:falsy 不是 false,参考这里)的值,或者是一个空对象,那么不会发生滚动。

举例:

scrollBehavior (to, from, savedPosition) {

return { x: 0, y: 0 }

}

对于所有路由导航,简单地让页面滚动到顶部。

返回 savedPosition,在按下 后退/前进 按钮时,就会像浏览器的原生表现那样

scrollBehavior (to, from, savedPosition) {

if (savedPosition) {

return savedPosition

} else {

return { x: 0, y: 0 }

}

}

如果你要模拟『滚动到锚点』的行为:

scrollBehavior (to, from, savedPosition) {

if (to.hash) {

return {

selector: to.hash

}

}

}

我们还可以利用路由元信息更细颗粒度地控制滚动。

 routes: [

{ path: \'/\', component: Home, meta: { scrollToTop: true }},

{ path: \'/foo\', component: Foo },

{ path: \'/bar\', component: Bar, meta: { scrollToTop: true }}

]

完整的例子:

import Vue from \'vue\'

import VueRouter from \'vue-router\'

Vue.use(VueRouter)

const Home = { template: \'<div>home</div>\' }

const Foo = { template: \'<div>foo</div>\' }

const Bar = {

template: `

<div>

bar

<div style="height:500px"></div>

<p id="anchor">Anchor</p>

</div>

`

}

// scrollBehavior:

// - only available in html5 history mode

// - defaults to no scroll behavior

// - return false to prevent scroll

const scrollBehavior = (to, from, savedPosition) => {

if (savedPosition) {

// savedPosition is only available for popstate navigations.

return savedPosition

} else {

const position = {}

// new navigation.

// scroll to anchor by returning the selector

if (to.hash) {

position.selector = to.hash

}

// check if any matched route config has meta that requires scrolling to top

if (to.matched.some(m => m.meta.scrollToTop)) {

// cords will be used if no selector is provided,

// or if the selector didn\'t match any element.

position.x = 0

position.y = 0

}

// if the returned position is falsy or an empty object,

// will retain current scroll position.

return position

}

}

const router = new VueRouter({

mode: \'history\',

base: __dirname,

scrollBehavior,

routes: [

{ path: \'/\', component: Home, meta: { scrollToTop: true }},

{ path: \'/foo\', component: Foo },

{ path: \'/bar\', component: Bar, meta: { scrollToTop: true }}

]

})

new Vue({

router,

template: `

<div id="app">

<h1>Scroll Behavior</h1>

<ul>

<li><router-link to="/">/</router-link></li>

<li><router-link to="/foo">/foo</router-link></li>

<li><router-link to="/bar">/bar</router-link></li>

<li><router-link to="/bar#anchor">/bar#anchor</router-link></li>

</ul>

<router-view class="view"></router-view>

</div>

`

}).$mount(\'#app\')

在网上查了一下,网友说还可以试试在main.js入口文件配合vue-router写这个

router.afterEach((to,from,next) => {

window.scrollTo(0,0);

});

 17.tips:webpack中alias配置中的“@”的作用

如题所示,build文件夹下的webpack.base.conf.js

resolve: {

extensions: [\'.js\', \'.vue\', \'.json\'],

alias: {

\'vue$\': \'vue/dist/vue.esm.js\',

\'@\': resolve(\'src\')

}

}

其中的@的意思是:只是一个别名而已。这里设置别名是为了让后续引用的地方减少路径的复杂度。

//例如

src

- components

- a.vue

- router

- home

- index.vue

index.vue 里,正常引用 A 组件:

import A from \'../../components/a.vue\'

如果设置了 alias 后。

alias: {

\'vue$\': \'vue/dist/vue.esm.js\',

\'@\': resolve(\'src\')

}

引用的地方路径就可以这样了

import A from \'@/components/a.vue\'

这里的 @ 就起到了【resolve(\'src\')】路径的作用。

 18.tips:package.json中的dependencies与devDependencies之间的区别

–save-dev 和 –save 的区别

我们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如:

  • –save-dev 安装的 插件,被写入到 devDependencies 对象里面去

  • –save 安装的 插件 ,被写入到 dependencies 对象里面去

devDependencies 是只会在开发环境下依赖的模块,生产环境不会被打入包内。

dependencies 是不仅在开发环境使用,在生成环境也需要。

 19.tips:package.json设置环境变量

三种方法可以在package.json设置环境变量。

先安装cross-env:

npm install --save-dev cross-env

package.json设置:

{

"scripts": {

"dev1": "export WEBPACK_ENV=production && npx webpack -p", ## mac

"dev1": "set WEBPACK_ENV=production && npx webpack -p", ## windows

"dev2": "cross-env CURRENT_ENV=development webpack-dev-server --inline --progress", ## 兼容所有平台

}

}

设置环境变量的作用:

在项目的js脚本中,通过process.env这个对象就可以访问到设置的环境变量结合打包软件webpack等等,实现不同的代码逻辑:

console.log(process.env.WEBPACK_ENV)

console.log(process.env.CURRENT_ENV)

 扩展参考:阮一峰:npm scripts 使用指南

以上是 【vue】常见开发知识点与问题整理(持续更新) 的全部内容, 来源链接: utcz.com/z/375854.html

回到顶部