vue2.0小结

  • 使用swiper的总结
    swiper5以上只支持vue3,所以需要使用低版本兼容,此处使用vue-awesome-swiper
    安装:npm install --save vue-awesome-swiper@3
    此时安装的是"vue-awesome-swiper": "^3.1.3",,而它依赖的swiper是4.5.1稳定版本。
    swiper的版本差异:链接
    swiper4-6版本的文档:链接
<template>
  <swiper :options="swiperOption" ref="mySwiper">
            <!-- slides -->
            <swiper-slide>slide1 </swiper-slide>
            <swiper-slide>slide2 </swiper-slide>
            <swiper-slide>slide3 </swiper-slide>
            <!-- Optional controls -->
            <div class="swiper-pagination" slot="pagination"></div>
   </swiper>
</template>
<script>
import { swiper, swiperSlide } from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.min.css'

export default {
  components: {
    swiper,
    swiperSlide
  },
  data() {
    return {
      swiperOption: {
        autoHeight: true,
        pagination: {
          el: '.swiper-pagination',
          clickable: true
        }
      }
    }
  },
}
</script>
  • vue中引入本地图片方式
  1. 直接在css中写样式
<div class="img1"></div>
// css
.img1{
   width: 55px;
   height: 55px;
   background: url(../assets/image/play.png) no-repeat center center;
   background-size: contain;
}

2.静态require图片

<div class="testImg" :style="{backgroundImage:`url(${testImg})`}"></div>
const testImg = require('../assets/image/play.png');
export default{
  data() {
    return {
      testImg,
    };
  },
}

3.动态引入图片

// item是一个数组对象
<span class="testImg" :style="{'background-image':`url(${require('../assets/image/'+item.type+'.png')})`}"></span>
  • Vue.js2.0中子组件修改父组件传递过来的props,但不影响父组件的原始数据:
    vue2.0中,子组件中不能修改父组件的状态,否则在控制台中会报错。
    但是经测试发现,这仅限于props为非数组及对象等引用类型数据,譬如字符串,数字等。如果props是对象或数组的话,在子组件内修改props的话,父组件是不会报错的,并且子组件中修改直接同步到父组件。那么要怎么解决修改props传的值而不污染父组件的值:
  1. 可以使用ES6提供的Object.assign({}, prop)的返回值就是一个全新的对象,操作这个新对象不会影响旧对象。如果不用ES6就自己递归实现拷贝器
  2. 可以给对象重新赋值:(给对象里的每一项重新赋值)
  • 多级组件嵌套传递数据:为减少多级组件传递数据时一级一级往下传的臃肿业务逻辑,使用$attrs$listeners

$attrs:包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind='$attrs'传入内部组件——在创建更高层次的组件时非常有用。
$listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on='$listeners'传入内部组件——在创建更高层次的组件时非常有用。
inheritAttrs:默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。

// A组件(App.vue)
<template>
  <div id="app">
    <child1 
      :p-child1="child1" 
      :p-child2="child2"
      v-on:test1="onTest1"  //此处监听了两个事件,可以在B组件或者C组件中直接触发
      v-on:test2="onTest2"></child1>
  </div>
</template>
<script>
import Child1 from './Child1.vue';
export default {
  data() {
    return {};
  },
  components: { Child1 },
  methods: {
    onTest1() {
      console.log('test1 running...');
    },
    onTest2() {
      console.log('test2 running');
    }
  }
};
</script>

// B组件(Child1.vue)
<template>
  <div class="child-1">
    <p>in child1:</p>
    <p>props: {{pChild1}}</p> // props: v_child1
    <p>$attrs: {{$attrs}}</p> // $attrs: { “p-child2”: “v_child2”}
    <hr />
    <!-- C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
    <!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
    <child2 v-bind="$attrs" v-on="$listeners"></child2>
  </div>
</template>
<script>
import Child2 from './Child2.vue';
export default {
  props: ['pChild1'],
  data() {
    return {};
  },
  inheritAttrs: false,
  components: { Child2 },
  mounted() {
    this.$emit('test1');
  },
};
</script>

// C 组件 (Child2.vue)
<template>
  <div class="child-2">
    <p>in child2:</p>
    <p>props: {{pChild2}}</p> // props: v_child2
    <p>$attrs: {{$attrs}}</p> // $attrs: {}
    <hr />
  </div>
</template>
<script>
export default {
  props: ['pChild2'],
  data() {
    return {};
  },
  inheritAttrs: false,
  mounted() {
    this.$emit('test2');
  },
};
</script>
  • 如果通过v-for 遍历想加不同的ref时记得加 :号,即 :ref =某变量 ;
    这点和其他属性一样,如果是固定值就不需要加 :号,如果是变量记得加 :号
<div v-for="(item ,index) in data" :key="index"  :ref="item.ref">

通过 :ref =某变量 添加ref(即加了:号) ,如果想获取该ref时需要加 [0],如this.$refs[refsArrayItem][0];如果不是:ref =某变量的方式而是 ref =某字符串时则不需要加,如this.$refs[refsArrayItem]

  • 对于所有的引用类型变量,console打印出来的值永远是你点开三角的那一刻的值,因此建议在console语句的后面设断点,这样打印出来的值是绝对正确的。当输出引用类型值时,前后两次console出来的结果都一样,可以用JSON.stringity(data)来区分前后两次的值。

  • 父组件与子组件之间的通信

  1. 父组件传值给子组件,通过props
  2. 子组件传值给父组件,通过$emit
<!-- 父组件 -->
<template>
  <div>
    <child :msg="msg" @msgEvent="setMsg"></child>
  </div>
</template>

<script>
import child from './child.vue';
export default {
  data() {
    return {
      msg: 'hi vue',
    };
  },
  components: { child },
  methods: {
    setMsg(m) {
      this.msg = m;
    },
  },
};
</script>

<style lang="less" scoped>
</style>

<!-- 子组件 -->
<template>
  <div>
    <p @click="updateMsg">{{msg}}</p>
  </div>
</template>

<script>
export default {
  props: {
    msg: String,
  },
  data() {
    return {}
  },
  methods: {
    updateMsg() {
      this.$emit('msgEvent', 'hello vue');
    },
  },
};
</script>

<style lang="less" scoped>
</style>
  • 如果在父组件想在子组件上监听自己的事件,需要加上native修饰符,否则点击无效
<router-link to=""  @click.native="hitClick"></router-link>
  • 编写template的时候,2.0必须要用一个根元素(如div)将代码片段包裹起来,否则报错。
  • 编写vue插件
    写插件:
//toast.vue 组件模板
<template>
  <div>
    <div v-show="show" class="toastContainer">
      <div class="toastText">{{text}}</div>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      show: false,
      text: '',
    }
  }
}
</script>

<style scoped>
.toastContainer {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  position: fixed;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  -webkit-transform: translateY(-50%);
  width: 100%;
  z-index: 9999;
  text-align: center;
}

.toastText {
  display: inline-block;
  max-width: 80%;
  background: rgba(0, 0, 0, 0.8);
  padding: 12px 22px;
  text-align: center;
  font-size: 15px;
  line-height: 22px;
  border-radius: 5px;
  color: #fff;
}

.hide {
  display: none;
}

.show {
  display: block;
}
</style>

//toast.js 插件
import toast from '../components/toast.vue'
// toast vm实例
let toastVm = null
// toast消失计时器
let timer = null

const Toast = {
  /**
   * Vue.js 的插件应当有一个公开方法 install
   * @param {constructor} Vue 构造器
   * @param {object} 可选的选项对象
   */
  install: function (Vue, options) {
    // 默认选项
    const opt = {
      duration: '2000'
    }
    for (let property in options) {
      opt[property] = options[property]
    }
    Vue.prototype.$toast = (text, duration = opt.duration) => {
      // 是否创建了实例
      if (!toastVm) {
        const ToastTpl = Vue.extend(toast) // 创建构造器
        toastVm = new ToastTpl() // 创建实例,实例处于“未挂载”状态
        const tpl = toastVm.$mount().$el // 在文档之外渲染并且随后挂载(toastVm.$mount('#app')直接挂在会替换#app)
        document.body.appendChild(tpl) // 使用原生DOM API把它插入文档
      }
      // 设置toast组件的状态
      toastVm.text = text
      toastVm.show = true

      // 清除上一个提示的计时器
      clearTimeout(timer)
      timer = setTimeout(() => {
        toastVm.show = false
      }, duration)
    }
  }
}
export default Toast

调用插件:

import Toast from './toast.js'
Vue.use(Toast)

在组件中使用:

this.$toast('toast text')

写好的插件还可以发布到npm平台
自己写的一个vue toast插件:vue-toast-cpn

  • 需求:判断图片是否存在,不存在则使用默认图片,使用onerror事件。
    法一:
<img :src="avatar1.png" :onerror="defaultImg" />

data() {
 return {
      // img 使用 onerror 以后,如果 onerror 指定的图片也是不存在的话,会出现无限死循环 404,为防止这种情况,加上this.onerror=null。
     defaultImg: 'this.src="./default.png";this.onerror=null',
   };
},

法二:

<div v-for="(item, index) in list" :key="item.id">
    <img :src="defaultImg(index,item.avatar)" :class="'img'+index" />
</div>

methods: {
    defaultImg(index, imgUrl) {
      const name = `img${index}`;
      // 异步等待dom渲染,不然会找不到元素
      setTimeout(() => {
        const ele = document.getElementsByClassName(name)[0];
        ele.setAttribute('src', 'default.png');
        ajax().get(imgUrl).then((res) => {
          if (res) {
            ele.setAttribute('src', imgUrl);
          }
        });
      }, 0);
    },
}
img { content: normal !important; }
  • 响应式修改数组的值
    错误操作:this.items[indexOfItem] = newValue --->无效
    正确操作:this.items.splice(indexOfItem, 1, newValue)

  • 很多时候用$emit携带参数传出事件,并且又需要在父组件中使用自定义参数时,这时我们就无法接受到子组件传出的参数了。
    找到了两种方法可以同时添加自定义参数的方法。

方法一
子组件传出单个参数时:
// 子组件
this.$emit('test',this.param)
// 父组件
@test='test($event,userDefined)'

方法二
子组件传出多个参数时:
// 子组件
this.$emit('test',this.param1,this.param2, this.param3)
// 父组件 arguments 是以数组的形式传入
@test='test(arguments,userDefined)'
  • 组件初始化时监听父组件异步传过来的值:
props: {
    data: {
      type: Object,
    },
  },
watch: {
    data: 'handleData',
  },
methods: {
    handleData() {
      // this.data的相关处理
  }
}
  • 由于html对属性及标签大小写不敏感,所以属性在浏览器中变成小写也是没关系的,但如果一定要写成大写的话,用setAttributeNS
document.getElementById('div1').setAttribute("slotCode", '1234');
浏览器中显示:
<div id="div1" slotcode="1234"></div>
document.getElementById('div1').getAttribute("slotCode") === "1234" // true
// =================
document.getElementById('div1').setAttributeNS(null, "slotCode", '1234');
浏览器中显示:
<div id="div1" slotCode="1234"></div>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • 1.安装 可以简单地在页面引入Vue.js作为独立版本,Vue即被注册为全局变量,可以在页面使用了。 如果希望搭建...
    Awey阅读 10,982评论 4 129
  • 有些时候,我只是想安静地做一些事,上课,吃饭,逛超市。
    茧忆阅读 169评论 0 0
  • 推荐 理性并非和感情相对,任何决定其实都是感情对感情的竞争,理性只是感情的武器。既然如此,自控的关键就不是调动理性...
    余小刚阅读 98评论 0 0
  • 没有国,哪有家,萨德问题愈演愈烈,乐天产品下架,超市关门,韩国游疑似被禁,平时看似不团结的中国人面对民族问题,国家...
    revora相望阅读 85评论 0 0