在vue中, 不容许直接绑定vuex的值到组件中, 如果直接使用, 则会报错 have no setterjavascript
方法一: 使用get和sethtml
// 在从组件的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) } } }
在路由里每一个都添加一个meta:vue
[{
path:'/login', meta: { title: '登陆页面' }, component:'login' }]
钩子函数,在main.js中添加以下代码:html5
router.beforeEach((to, from, next) => {
window.document.title = to.meta.title; next() })
经过form表单提交,html代码以下:java
<input name="file" type="file" accept="image/png,image/gif,image/jpeg" @change="update"/>
JS代码:react
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; } }) }
qs库的npm地址:https://www.npmjs.com/package/qswebpack
功能虽然都是序列化。假设我要提交的数据以下:ios
var a = {name:'hehe',age:10};
qs.stringify序列化结果以下:name=hehe&age=10
git
而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('登登陆出现错误'); })
//设置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(); } }
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 } }
可参考地址:
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》
若是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 解决方案的缺陷在于, 在数据传递过程当中,两个组件必须都已经被渲染过。
由于使用了 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";
在项目的根目录下找到 .babelrc 文件,增长 "compact": false ,如:
{
"compact": false, "presets": ["env", "react", "stage-0"], "plugins": [ "transform-runtime" ] }
若是不存在则手动建立该文件,并填写内容如:
{
"compact": false }
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}}); }
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不支持的字体格式,引入pdf.js的字体试试
const CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.489/cmaps/';
pdfjsLib.getDocument({
data: pdfData,
cMapUrl: CMAP_URL,
cMapPacked: true, })
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://www.javashuo.com/article/p-gkqnorig-bx.html
在webpack.dev.config.js中找到 devServer下的hot,再下面添加 disableHostCheck: true,来解决127.0.0.1指向其余域名时出现"Invalid Host header"问题
如图所示:
有时候咱们须要页面滚动条滚动到某一固定的位置,通常使用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); });
如题所示,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')】路径的做用。
–save-dev 和 –save 的区别
咱们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,好比:
–save-dev 安装的 插件,被写入到 devDependencies 对象里面去
–save 安装的 插件 ,被写入到 dependencies 对象里面去
devDependencies 是只会在开发环境下依赖的模块,生产环境不会被打入包内。
dependencies 是不只在开发环境使用,在生成环境也须要。
三种方法能够在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 使用指南