- 使用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中引入本地图片方式
- 直接在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传的值而不污染父组件的值:
- 可以使用ES6提供的Object.assign({}, prop)的返回值就是一个全新的对象,操作这个新对象不会影响旧对象。如果不用ES6就自己递归实现拷贝器
- 可以给对象重新赋值:(给对象里的每一项重新赋值)
-
多级组件嵌套传递数据
:为减少多级组件传递数据时一级一级往下传的臃肿业务逻辑,使用$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)
来区分前后两次的值。父组件与子组件之间的通信
- 父组件传值给子组件,通过
props
- 子组件传值给父组件,通过
$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);
},
}
- 分享一篇vue框架的适配方案:如何在Vue项目中使用vw实现移动端适配
其中需要注意的是,Viewport Units Buggyfill有一个bug,在<img>中content样式会引起部分浏览器下,图片不会显示。需要全局添加样式处理:
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>