vue2实践(持续更新)

segmentfault 会及时更新,这个定期更新。

记录一些小技巧和踩过的坑

1. props 带不带冒号的区别

 <child1 ref="child1" msg="{name:'bill'}"></child1>
 
 <child1 ref="child1" :msg="{name:'bill'}"></child1>

首先冒号是v-bind的缩写,不带冒号后面是字符串,带了冒号就是数据绑定,引号里面的内容是变量或者表达式,
组件内不能修改props的值,同时修改的值也不会同步到组件外层,即调用组件方不知道组件内部当前的状态是什么

vue 组件props传递时,为什么有时候需要加冒号,有时候不需要?
如何在Vue2中实现组件props双向绑定

2. computed属性,可以set,但是设置的是data返回的数据,不能设置自身。

如果计算属性是对象的话,可以设置他的属性。

3. 组件的生命周期函数是在template标签里的数据发生变化时候触发update

数据可能更新了,但是没有绑定到dom上面的话,不会调用update钩子函数。

4. 给变data的第二季属性的值,data不会更新,导致组件不会更新

所以在这个时候应该用Object.assign()重新生成新的对象。第一级属性值更新的话,data是更新的!

5. 动态绑定style的话,后面的样式值不能加分号

  style = {
            color: "rgb(66, 180, 232)"
       };
  //下面渲染不出来
    style = {
            color: "rgb(66, 180, 232)";
       };

6. filter 过滤器

vue2.0 的时候把过滤器移除了,现在2.10又加了上去,

定义filter过滤器:
写在实例Vue内部的是局部过滤器,

new Vue({
  filters:{
  formatMoney: function (value){
      return "$"+value.toFixed(2);
   }
 }
})

写在外部的是全局过滤器

Vue.filter("money", function (vaule, type) {
    return "¥" + vaule.toFixed(2) + type;
})

组件内调用:

<span v-text="message | wrap 'before' 'after'"></span>//1.x的写法,2直接wrap('before','after')调用
Vue.filter('wrap', function (value, begin, end) {
  return begin + value + end
})

补充下:一个竖线 | 在js中是二进制运算

想问一下这个用竖线分隔开是什么意思

7. watch监测对象或者数组,不是替换对象或者数组,newVal和oldVal是同一个值。

注意:在变异(不是替换)对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变异之前值的副本。

vm.$watch

8. 为组件绑定原生事件

有时候,你可能想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:

<my-component v-on:click.native="doTheThing"></my-component>

9. 2.1.6computed在beforeMount前面执行的,vue2.2.1刚好相反

10. v-for和v-if在同一个标签使用的话,v-for的优先级高于v-if

如果在同一标签使用,v-if就是用来过滤v-for里面的数据的,先走if的话用template套在外面

今天并列使用的时候遇到的巨坑:

<topic v-for="(topic,idx) in topics" :model="topic" :showIdx="false" :clickHandler="handleTopicClick"  v-if="mode==0"/>
<school-topic v-for="t in topics" :model="t" :style="showStyle(t)" :clickHandler="handleTopicClick" v-else />

结果topics只有三条数据,但是渲染出9条数据,官网说的很清楚:v-for with v-if

11.keep-alive 缓存组件在内存中,再次进入该页面不会重新渲染,用于保存页面的原始状态

<template>
    <div id="app">
        <keep-alive include="SelectTopics">
            <router-view></router-view>
        </keep-alive>
    </div>
</template>

即使设置了keep-alive组件的beforeUpdateupdated钩子函数还是会调用的。

activated和unactivated钩子是在keep-alive组件里面被调用的,不是第一次进入keep-alive组件的话,调用顺序是:
beforeEach->beforeRouteEnter->activated->beforeUpdate->beforeRouteEnternext函数

也可以在离开页面的时候手动销毁改组件:

 beforeRouteLeave(to, from, next) {
    if (to.path === "/examcentre") {
        this.$destroy();
    }
    next();
 }
//或者
  deactivated: function () {
    console.log(4)
    this.$destroy();
  },

有时候根据需求(比如该组件是复用的)需要在再次进入该页面的时候重新从后台获取数据,那么可以在activated钩子函数中请求数据来update页面。

vue.js 能否设置某个组件不被keep-alive?
vue2.0 keep-alive最佳实践
Vue如何做到前进刷新数据,后退不刷新数据呢?
<keep-alive>组件缓存问题
Vue路由开启keep-alive时的注意点
vue.js+vue-router+webpack keep-alive用法

浏览器的前进回退并不会走dom绑定的前进后退的事件

所以要想清除vuex state里面的数据的话,可以放在beforeRouteLeave里面做处理。

 this.$store.commit("SET_PAPERATTRIBUTE", {}); 

弹窗组件

mint-ui 中的Toast MessageBox Indicator 调用的方式是Toast('提示信息');或者在全局引入mint-ui然后再组件里this.$toast("提示信息"),这种方式和我们普通的引入组件的方式都不同,通常我们是在模板里直接将组件放到模板里面,这就意味着父组件在render的时候,子组件也被render到了dom里面:

<template>
    <div class="my-set-attr-wrap">
        <set-attribute ref="setMyAttr" :style="setAttrStyle" :model="attributeModel" />
    </div>
</template>

this.$toast("提示信息")这种是在函数中调用,肯定也是要render到dom里面的,改咋办呢?查看了mint-ui的实现方式:document.body.appendChild(instance.$el);
目录:

clipboard.png
clipboard.png

TopicDetailPopup.vue文件就是普通的vue写法,
index.js:

clipboard.png
clipboard.png

这里考虑到每次弹出层不能都去创建新的组件,我们只需要将组件内的数据更新就可以了,dom也不需要删除,然后再创建,就用到了单例模式,这边的instance是在父组件没销毁之前都是存在的,每次只是更新了组件的数据,为啥没被销毁呢,这边形成了一个闭包:


clipboard.png
clipboard.png

调用:

import TopicDetailPopup from '../topicDetailPopup/index.js'
TopicDetailPopup.open({
                            detail: res.data
                     });

但是这个地方出现个问题this.$store现在为undefined,应该是因为这个组件是直接new实例化的,而不是通过根组件嵌套的,
main.js

new Vue({
    router: router,
    store,
    render: h => h(App)
}).$mount("#app");

store注册在根组件里面,而弹窗组件没有和根组件关联,所以拿不到store。

要是能将弹窗组件插入其他组件问题就能解决了,貌似现在API没有提供这样的接口,vue2动态添加组件的话可以用render函数,可以我现在的弹窗组件是模板的形式,也可以动态插入到父组件,<component :is="componentId"></component>且需要在components里面引用,这样又回到了模板语法了。

弹窗的弊端:
vue-devtools 没法检测到组件,也没法检测到vuex,对于webapp来说返回键没法使用,关闭不了当前的弹窗,造成上面的问题都是由于没用使用router。
对于安卓手机返回键没法使用可以采用曲线救国的方式,禁用返回键,js没法直接操作安卓返回键,但是可以使用beforeRouteLeave,使得返回键没有效果,

 beforeRouteLeave(to, from, next) {
        if (this.popupVisible) {//弹窗显示的话,路由没法跳转
            next(false);
        } else {
            next(true);
        }
 }

弹窗的好处:
在当前页面直接弹出,这样可以保存当前页面的数据和滚动条的位置,还有就是组件复用的话,直接关闭弹窗,不需要根据不同的页面去回退或者前进到特定的页面。

使用的是vue2.0,如何动态添加组件。例如实现点击A按钮添加aTest组件,点击B按钮添加bTest组件。

:model和v-model的区别

v-model通常用于input的双向数据绑定<input v-model="parentMsg">,也可以实现子组件到父组件数据的双向数据绑定:
首先说说v-model的用法:
model.vue

<template>
    <div>
        父:
        <input type="text"
               v-model="msg">
        <child v-model="msg"></child>
    </div>
</template>
<script>
import child from './modelChild.vue'
export default {
    name: "model",
    props: {

    },
    components: {
        child
    },
    data() {
        return {
            msg: "ppp"
        }
    },
    methods: {

    }
}
</script>
<style lang="less">

</style>

modelChild.vue

<template>
    <div>
        子:
        <input type="text"
               @input="handleInput"
               class="text"
               :value="value">
    </div>
</template>
<script>
export default {
    name: "modelChild",
    props: ["value"],
    methods: {
        handleInput(e) {
            this.$emit("input", e.target.value)
        }
    }
}
</script>
<style lang="less">
.text {
    height: 20px;
    width: 200px;
}
</style>

无论改变父组件还是子组件的输入框,value和msg的值都会改变,两个输入框的值也就同时改变了。

:model和v-model的区别
:model是v-bind:model的缩写,<child :model="msg"></child>这种只是将父组件的数据传递到了子组件,并没有实现子组件和父组件数据的双向绑定。当然引用类型除外,子组件改变引用类型的数据的话,父组件也会改变的。

Vue.component注册全局组件

查看vue-router源码的时候发现install.js里面两句:

Vue.component('router-view', View)
Vue.component('router-link', Link)

这两句就是全局注册了这两个组件,

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
clipboard.png
clipboard.png
clipboard.png
clipboard.png

这三步后,在组件里直接使用<router-view></router-view>而不用先import再使用。

在mint-ui里也是相同的做法:
src/index.js

const install = function(Vue) {
  if (install.installed) return;
  Vue.component(Header.name, Header);//注册全局组件
  Vue.component(Button.name, Button);
  Vue.use(InfiniteScroll);//使用指令插件
  Vue.use(Lazyload, {
    loading: require('./assets/loading-spin.svg'),
    try: 3
  });//使用指令插件或lazy-component
  Vue.$messagebox = Vue.prototype.$messagebox = MessageBox;
  Vue.$toast = Vue.prototype.$toast = Toast;
  Vue.$indicator = Vue.prototype.$indicator = Indicator;
};

后面的Vue.$toast = Vue.prototype.$toast = Toast;使得我们可以在组件中直接调用this.$toast("提示信息")

组件上写class

clipboard.png
clipboard.png

之前在写react的时候是不可以这么做的,今天查看了popup.vue的时候发现vue是可以这么干的,直接渲染到了组件的根元素上面。用在组件上

Boolean类型的props可以直接定义:

clipboard.png
clipboard.png
 props: {
    fixed: Boolean,
    value: {}
  }

数据更新页面没刷新

今天在concat两个数组的时候发现数据更新了,页面并没有刷新,debug看了下数据,concat的数据没有get set属性访问器,导致后来push的数据也没有属性访问器。之前没有细看文档。搜了下原来push是变异方法,concat不是。
解决办法有二:

  • 使用变异方法
  • 使用vue component的$set函数
    看一些小伙伴的回答是data的$set方法,至少vue2是没有的。具体可查看文档列表渲染
    我的解决办法是:
Array.prototype.push.apply(arr, item);

render函数和模板语法只能二选一

今天在模板.vue文件里加入render函数发现并不会执行render函数,原来是vue-loader会将template转成render函数,所以只能二选一。.vue文件如何使用render函数渲染组件

控制input只能输入数字

<input type="number">在pc和手机端都可以实现只能输入数字,可是手机端弹出的软键盘里面没有完成或者搜索按钮,搜了下,现在的HTML5 number的情况下并没有支持搜索按钮,type='text'是有的。所以曲线救国,控制表单只能输入数字。
起初的想法是先把在

<input type='text' @input="handleInput" :value="val"/>

handleInput(e){
this.val=e.target.value.replace(/[^\d]/g,'');
}

但是这种并不会实时刷新表单的数据,下面就会起作用

e.target.value=e.target.value.replace(/[^\d]/g,'');

优雅点的写法,用自定义指令:

//<input type="text" v-number-only />
 directives: {
        numberOnly: {
            bind: function(el) {
                el.handler = function() {
                    el.value = el.value.replace(/\D+/, '')
                }
                el.addEventListener('input', el.handler)
            },
            unbind: function(el) {
                el.removeEventListener('input', el.handler)
            }
        }
    },

vue的input中,如何限制只能输入number

弹出层弹出文本框获取焦点

由于弹出层是单例模式,所以打开弹出层只会执行一次mounted钩子函数,我去监听

  visible(val) {
            if (val) {
                this.$refs.textbox.focus();//这样并不能使文本框获取焦点
            } else {
                this.detail = null;
                this.$refs.textbox.value = "";
            }
        }

解决办法也是使用自定义指令

  focus: {
            update(el) {
                el.focus();
            }
  }

vue如何实现点击button 使input获取焦点

改变v-html解析后台返回的HTML样式

平时在写组件里面的样式加上scoped,避免样式的全局污染,而从后台返回的HTML无效的,解决办法就是在组件里再加一对style标签,将样式写到这里。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,478评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,825评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,482评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,726评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,633评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,018评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,168评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,320评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,264评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,288评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,995评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,587评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,909评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,284评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,862评论 2 339

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,043评论 0 29
  • 1.安装 可以简单地在页面引入Vue.js作为独立版本,Vue即被注册为全局变量,可以在页面使用了。 如果希望搭建...
    Awey阅读 10,973评论 4 129
  • 由于我是从一个旧的项目上面改得代码,旧的项目启动页,我把它删除了,由于新项目的启动页还没有做好。所以暂时就空起了。...
    FengxinLi阅读 347评论 0 1
  • 如果我告诉你,大家的情况几乎都是这样,但是有解决方案,你相信吗? 我的工作是组建完整的产品研发团队,包括工程师、设...
    启庵阅读 482评论 0 2
  • 妈妈 我爱您 我希望您头发不会白 我希望您背不会驼 我希望您身体健康 我希望岁月善待您!
    绵海宝宝阅读 101评论 0 0