vue2知识点实战

来源:互联网 发布:ios应用网络设置 编辑:程序博客网 时间:2024/06/09 01:08

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

由于本篇文章内容太多,导致SF编辑器有点卡,所以新开辟了一篇 vue2实践(二),后续再这里更新。

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);
目录:

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

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

调用:

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)

这三步后,在组件里直接使用 <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

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

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

 props: {    fixed: Boolean,    value: {}  }

数据更新页面没刷新

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

  • 使用变异方法

  • 使用vue component的$set函数
    看一些小伙伴的回答是data的$set方法,至少vue2是没有的。具体可查看文档列表渲染

我的解决办法是:

Array.prototype.push.apply(arritem);

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标签,将样式写到这里。


转载https://segmentfault.com/a/1190000008688050

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 流产后子宫内膜薄怎么办 人流后内膜过厚怎么办 子宫内膜薄月经量少怎么办 子宫内膜很薄该怎么办 月经量少子宫内膜薄怎么办 子宫内薄没月经怎么办 感冒20多天不好怎么办 皮肤干燥又痒怎么办了 眼周皮肤很干怎么办 产后掉头发很厉害怎么办 班上学生很吵怎么办 进了网贷黑名单怎么办 预约了挂号没去怎么办 吃完米索手心痒怎么办 三岁宝宝湿疹了怎么办 割完剥皮后水肿怎么办 微医预约挂号后怎么办 人流后出现腰疼怎么办 生育服务单丢了怎么办 客厅地面砖坏了怎么办 门锁很涩不好开怎么办 胶水粘到手机上怎么办 沾鞋胶水粘到手怎么办 轮胎内衬板坏了怎么办 轿车后减震异响怎么办 租的房间隔音差怎么办 彩钢房顶下雨响怎么办 酷派手机开不开机怎么办 酷派手机无法开机怎么办 酷派手机丢了怎么办 实木家具掉漆了怎么办 木桌子上有划痕怎么办 烤漆家具掉漆怎么办 洗碗帕沾了油污怎么办 手被棍子打肿了怎么办 楼上弄的声音大怎么办 楼上太吵楼下人怎么办 严重多囊卵巢该怎么办 被医院骗了应该怎么办 四维胎儿不配合怎么办 孕甲状腺tsh有点偏高怎么办