由于上篇文章内容太多,导致SF编辑器有点卡,所以新开辟了一篇,也方便阅读。
elementUI样式是全局的
之前在用mint-ui的时候每个组件里面都有style标签,样式都是内部的,公用的写在了mint-ui/lib/style.css
文件里并且该样式文件就是在mint-ui项目里,但是element组件里都没有style标签,翻看了一会,发现element可以自定义主题,而mint不可以,这样element的样式全写成了全局的,这样方便用户配置主题。样式文件写在packages/theme-default/src
内,打包element的时候会将theme-default这个独立的库放到打包好的文件夹内。theme-default针对每个组件有个对应的css文件,index.css去@import
@import "./base.css";
@import "./pagination.css";
@import "./dialog.css";
@import "./autocomplete.css";
@import "./dropdown.css";
@import "./dropdown-menu.css";
@import "./dropdown-item.css";
@import "./menu.css";
@import "./submenu.css";
@import "./menu-item.css";
@import "./menu-item-group.css";
@import "./input.css";
@import "./input-number.css";
@import "./radio.css";
@import "./radio-group.css";
@import "./radio-button.css";
@import "./checkbox.css";
@import "./checkbox-group.css";
...
style直接写在组件上会起作用
<topic :style="topicDialogStyle"></topic>
computed: {
topicDialogStyle() {
return {
maxHeight: "65vh",
overflow: "auto"
}
}
}
上篇提到class直接写在组件上面是会渲染到组件的根节点上面,惯性思维,认为style也会在跟组件上起作用,测试了下是会起作用的,
如果组件的style都用scoped修饰,那么每个组件的样式都是在本组件起作用,即使className渲染到了子组件的根节点,在父组件中定义的相同className的style也不会起作用,因为加了scoped以后组件的每个HTML标签都被加了一个data属性,
1的地方是根节点,有两个data属性,这个不知道为啥,里面的子节点都是一个data属性,并且都是相同的。再看看vue对加了scoped的style做了啥,
中括号里就是data属性,每个组件data属性都不同,保证了每个组件scoped的样式只在当前组件中有效。既然父组件中定义的样式对子组件无效咋办,有很多解决办法:
- 利用class可以在组件上直接写,子组件可以约定不同的className,子组件里面写几套style
- 通过props将在父组件定义的style对象传递进去
- 在父组件中再开辟个不加scoped属性的style,不过这么写可能污染到其他组件的样式。
- 在子组件添加style属性,直接影响子组件根元素的样式
发现个奇怪的现象,在父组件中设置line-height(是scoped)子组件的所有行高都受影响,也就是所有的子元素都继承了这个属性,不设置行高默认为normal,所以解决办法就是给子组件的外层设置line-height:normal
style直接写在组件上面,会对根元素起作用,
<el-input-number size="small" :style="{color:'blue'}"></el-input-number>
<el-input-number size="small" style="color:blue"></el-input-number>
"vue": "2.2.2",不知道什么原因,后续再看。
自定义element dialog宽度
由于style 加了 scoped ,所以里面每个样式都是CSS [attribute] 选择器只对加了attribute属性的标签有效,而dialog很多是全局样式,想改变dialog的高度写在scoped里面是无效的,所以可以写在不加scoped标签的style里面,
custom-class Dialog 的自定义类名 string — —
通过custom-class props去控制dialog的总体样式,同时要注意改classname的唯一性,以防污染其他组件。
router-view标签创建的命名路由并不会在每次切换路由的时候销毁
app.vue
<template>
<div id="app">
<router-view name="header"></router-view>//头部有搜索框和logo
<router-view name="nav"></router-view>//tab导航栏
<router-view></router-view>
</div>
</template>
router/index.js
{
path: '/',
name: 'Login',
component: Login
},
{
path: '/index',
name: 'Index',
components: {
default: Index,
header: Header,
nav: Nav
}
},
{
path: '/paperDetail',
name: 'PaperDetail',
components: {
default: PaperDetail,
header: Header,
nav: Nav
}
},
因为登录页是独立的,不需要头部和导航栏,所以要使用命名路由去动态匹配除了登录页的其他页面,本以为这么动态匹配的header.vue
和nav.vue
是在导航栏切换的时候被销毁的,无意间发现beforeMount
和beforeDestroy
钩子函数并不会在导航栏切换的时候调用,(beforeRouteEnter
和beforeRouteLeave
任然会被正常调用,调用顺序是enter->watch route->leave,)那么这么就不会增加格外的内存开销,就等同于写死组件在根组件:
<template>
<div id="app">
<header></header>
<navbar></navbar>
<router-view></router-view>
</div>
</template>
正如官网所述,
小结:针对不同路由需要不同的数据话,可以去监听路由的变化,但是这个监听只针对复用组件,比如header.vue,对于paperDetail.vue这种没有复用的组件是无效的。
设置position:absolute对没有加position定位的父组件不会起冒泡效果
<div class="top-pane" @click="handleItemClick" v-else>
<ul class="blue-pane" @click="handleUlClick">
<li class="normal-line play-button-pane" @click.prevent="handleBtnClick" v-show="showPlayButton">
<img src="../assets/imgs/play-btn.png" alt="">
</li>
</ul>
</div>
css
.top-pane {
.blue-pane {
height: 250px;
position: relative;
.play-button-pane {
position: absolute;
top: 50%;
left: 50%;
margin-top: -40px;
margin-left: -40px;
>img {
width: 80px;
}
}
}
}
点击play-button-pane handleItemClick并不会执行,而handleUlClick可以执行,说明事件并没有冒泡到没有添加position的top-pane节点,而冒泡到了添加position:relative的blue-pane节点。具体为啥,有待讨论。
页面刷新beforeRouteEnter钩子函数中的from.path为"/"
一直以为页面刷新和router.push()的方式是一样的,拿到的from.path都是上次路径,使用中发现并不是如此,每次页面刷新,不管是从哪个组件跳转过来的,from.path都是"/"
深度作用选择器 >>>
起因,我想对element的carousel的高度根据屏幕的大小进行调整,但是API只提供了height属性,但是我不想用js拿到屏幕宽度去控制height,我想用media query控制
<el-carousel trigger="click" height="800px" class="index-carouse pc-index-carouse">
<el-carousel-item v-for="(item,index) in carouse" :key="index">
<a :href="item.imgLink">
<img :src="item.src" alt="">
</a>
</el-carousel-item>
</el-carousel>
<style lang="less" scoped>
.pc-index-carouse {
height: 400px;
.el-carousel__container {
height: 100% !important;
}
}
</style>
因为加了scoped 节点有了data-v-277d1ceb属性
.pc-index-carouse .el-carousel__container[data-v-277d1ceb] {
height: 100% !important;
}
但是classname属性data-v-277d1ceb加在了.el-carousel__container上,应该只加在.pc-index-carouse上这个时候就该深度作用选择器出场了
.pc-index-carouse {
height: 400px;
/deep/ .el-carousel__container {
height: 100% !important;
}
}
编译后的样式
.pc-index-carouse[data-v-277d1ceb] .el-carousel__container {
height: 100% !important;
}
这样就通过样式改变了carousel的高度
浅谈vue中style的scoped属性(修改特定Element组件样式的方法)
Scoped CSS
锚点定位报错
vue-router Failed to execute 'querySelector' on 'Document'
原来是因为我每个节点的id都是数字,变成字符串就好了
scrollBehavior (to, from, savedPosition) {
if (to.hash) {
return {
selector: to.hash
}
}
}
关于Failed to execute 'querySelectorAll' on 'Document': '#1517905886124' is not a valid selector."
组件自定义事件传参
用的是vant的小程序版的swipe-cell
if (this.data.asyncClose) {
this.$emit('close', {
position: position,
instance: this
});
} else {
this.swipeMove(0);
}
父组件里使用swipe-cell
<van-swipe-cell
:right-width="65"
:left-width="65"
async-close
:key="item._id"
v-for="item in list"
@close="onSwipeClose(arguments,item)"
>
尝试了各种办法都不能获得两个参数,onSwipeClose.bind(item) 也不行,onSwipeClose返回函数也不行;arguments就是上面emit出去的参数,item就是循环的item。
vuex action 只能传递一个额外参数
传递两个参数都有值
到action里丢了,只剩dishName
所以只能传递一个对象或者数组
Only one parameter works when dispatching actions.
props跟attribute区别
比如:
<blog-post post-title="hello!"></blog-post>
post-title可能是props也可能是attribute
那么什么时候post-title是props什么时候是attribute?
上代码:
App.vue
<template>
<div id="app">
<HelloWorld msg="Hello Vue!" v-bind="{ name: 'geek', age: 10 }" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld,
},
};
</script>
HelloWorld.vue
<template>
<div class="hello">
<h3>Installed CLI Plugins</h3>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
mounted() {
console.info("props:", this.$props);
console.info("attr:", this.$attrs);
},
};
</script>
输出:
HelloWorld的props中只定义了msg所以props只包含msg,其他的都属于attribute。
改下HelloWorld.vue
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
name: String,
age: Number,
},
mounted() {
console.info("props:", this.$props);
console.info("attr:", this.$attrs);
},
};
</script>
输出:
这个时候从父组件传递的所有属性都属于props
attribute的其他作用
attribute会默认将属性加载在根节点,比如第一个例子的name age属性
如果根节点定义了传递进来的attribute会怎样?会被覆盖(class
和 style
attribute 会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:)具体参考替换-合并已有的-Attribute
当然也可以在组件设置inheritAttrs:false
(2.4.0新增)阻止attribute被设置到组件的根节点,但这个选项不影响 class
和 style
绑定
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。