[总结]vue开发常见知识点及问题资料整理(持续更新)

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

–save-dev–save 的区别

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

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

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

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

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

注:可通过NODE_ENV=developementNODE_ENV=production指定开发还是生产环境。

(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()
})

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

首先安装axios:
1.利用npm安装npm install axios –save
2.利用bower安装bower install axios –save
3.直接利用cdn引入

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

一般情况上传照片有两种方式:

  • 1.本地图片转换成base64,然后通过普通的post请求发送到服务端。操作简单,适合小图,以及如果想兼容低版本的ie没办法用此方法
  • 2.通过form表单提交。form表单提交图片会刷新页面,也可以时form绑定到一个隐藏的iframe上,可以实现无刷新提交数据。

这里只讲解一下第二种方式:
html代码:

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

js代码:

import axios from 'axios'
// 添加请求头
update (e) {   // 上传照片
      var self = this let file = e.target.files[0] /* eslint-disable no-undef */ let param = new FormData() // 创建form对象 param.append('file', file) // 通过append向form对象添加数据 param.append('chunk', '0') // 添加form表单中其他数据 console.log(param.get('file')) // FormData私有类对象,访问不到,可以通过get判断值是否传进去 let config = { headers: {'Content-Type': 'multipart/form-data'} } // 添加请求头 axios.post('http://172.19.26.60:8081/rest/user/headurl', param, config) .then(response => { if (response.data.code === 0) { self.ImgUrl = response.data.data } console.log(response.data) }) }

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('登登录出现错误'); })

 vue中实现全局的setCookie,getCookie以及delCookie方法笔记

import Vue from 'vue'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import App from '../component/App.vue'
import Login from '../component/Login.vue'
import UserInfo from '../component/UserInfo.vue'
//状态管理
Vue.use(Vuex)
  //路由
Vue.use(VueRouter)

//路由配置
//如果需要加菜单,就在这里添加路由,并在UserMenu.vue添加入口router-link
const router = new VueRouter({
  routes: [{
    path: '/login',
    component: Login
  }, {
    path: '/user_info',
    component: UserInfo
  }]
})

//Vuex配置
const store = new Vuex.Store({
  state: {
    domain:'http://test.example.com', //保存后台请求的地址,修改时方便(比方说从测试服改成正式服域名)
    userInfo: { //保存用户信息
      nick: null,
      ulevel: null,
      uid: null,
      portrait: null
    }
  },
  mutations: {
    //更新用户信息
    updateUserInfo(state, newUserInfo) {
      state.userInfo = newUserInfo;
    }
  }
})

//设置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]);
    else
        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();
  }

//vue实例
var app = new Vue({
  data: {},
  el: '#app',
  render: h => h(App),
  router,
  store,
  watch:{
    "$route" : 'checkLogin'
  },
  created() {
    this.checkLogin();
  },
  methods:{
    checkLogin(){

      //检查是否存在session
      if(!this.getCookie('session')){
        this.$router.push('/login');
      }else{
        this.$router.push('/user_info');
      }
    }
  }
})

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')】路径的作用。

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

如何在 vue 项目里正确地引用 jquery 和 jquery-ui的插件

使用vue-cli构建的vue项目,webpack的配置文件是分散在很多地方的,而我们需要修改的是build/webpack.base.conf.js,修改两处的代码

// 在开头引入webpack,后面的plugins那里需要
var webpack = require('webpack')
// resolve  module.exports = { // 其他代码...  resolve: { extensions: ['', '.js', '.vue'], fallback: [path.join(__dirname, '../node_modules')], alias: { 'src': path.resolve(__dirname, '../src'), 'assets': path.resolve(__dirname, '../src/assets'), 'components': path.resolve(__dirname, '../src/components'), // webpack 使用 jQuery,如果是自行下载的 // 'jquery': path.resolve(__dirname, '../src/assets/libs/jquery/jquery.min'), // 如果使用NPM安装的jQuery 'jquery': 'jquery' } }, // 增加一个plugins  plugins: [ new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery" }) ], // 其他代码... }

这样就可以正确的使用jQuery了,比如我要引入Bootstrap,我们在vue的入口js文件src/main.js开头加入

// 使用Bootstrap
import './assets/libs/bootstrap/css/bootstrap.min.css'
import './assets/libs/bootstrap/js/bootstrap.min'

这样Bootstrap就正确的被引用并构建。
在比如使用toastr组件,只需要在需要的地方import进来,或者全局引入css在需要的地方引用js,然后直接使用

// 使用toastr
import 'assets/libs/toastr/toastr.min.css'
import toastr from 'assets/libs/toastr/toastr.min'

toastr.success('Hello')

参考:

vue-cli webpack全局引入jquery

1.首先在package.json里加入,

dependencies:{
 "jquery" : "^2.2.3"
}

然后 npm install

2.在webpack.base.conf.js里加入

var webpack = require("webpack")

3.在module.exports的最后加入

plugins: [
 new webpack.optimize.CommonsChunkPlugin('common.js'),
 new webpack.ProvidePlugin({
     jQuery: "jquery", $: "jquery" }) ]

4.然后一定要重新 run dev

5.在main.js 引入就ok了

import $ from 'jquery'

参考: vue-cli怎么引入jquery

在.vue文件中引入第三方非NPM模块

var Showbo = require("exports?Showbo!./path/to/showbo.js");

参考: exports-loader

vue-cli引入外部文件

webpack.base.conf.js 中添加externals

externals 中 swiper 是键,对应的值一定的是插件 swiper.js 所定义的变量 Swiper :

之后再在根目录下的index.html文件里引入文件:<script src="static/lib/swiper.js"></script>
这样子就可以在需要用到swiper.js的文件里加入这行代码:import Swiper from 'swiper',这样就能正常使用了。
参考: https://segmentfault.com/q/1010000005169531?_ea=806312

 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》

vue非父子组件通信

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

let Hub = new Vue(); //创建事件中心

组件1触发:

<div @click="eve"></div>
methods: {
    eve() {
        Hub.$emit('change','hehe'); //Hub触发事件
    }
}

组件2接收:

<div></div>
created() {
    Hub.$on('change', () => { //Hub接收事件
        this.msg = 'hehe';
    });
}

 可参考: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接收:

<div></div>
created() {
    this.$root.Bus.$on('change', () => { //接收事件
        this.msg = 'hehe';
    });
}

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

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 方法接收 tofrom 路由对象。第三个参数 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);
});

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"]
    }
};

注意:在配置文件中不要使用const,let。在IE9低版本浏览器不支持该语法(打包的时候有可能引入了配置文件的内容)。

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

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

在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}});
}

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

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

{
  "compact": false,
  "presets": ["env", "react", "stage-0"],
  "plugins": [
    "transform-runtime"
  ]
}

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

{
  "compact": false
}

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);
} 

 后台返回pdf的base64编码到前端预览,如果pdf中有中文,显示有问题解决办法

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

const CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.489/cmaps/';
pdfjsLib.getDocument({
    data: pdfData,
    cMapUrl: CMAP_URL,
    cMapPacked: true,
    })

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值