title: Vue脚手架
date: 2023-03-06 15:10:21
tags: Vue
一、 脚手架文件结构
|--node_modules
|--public
| |--favicon.ico:页签图标
| |--index.html:主页面
|--src
| |--assets:存放静态资源
| | |--logo.png
| |--component:存放组件
| | |--Helloworld.vue
| |--App.vue: 汇总所有组件
| |--main.js:入口文件
|--.gitignore: git版本管制忽略的配置
|--babel.config-js: babel的配置文件
|--package.json:应用包配置文件
|--README.md:应用描述文件
|--package-lock.json:包版本控制文件
二、关于不同版本的Vue:
- vue.js与vue.runtime.xxx.js的区别:
- vue.js是完整版,包含核心功能+模板解析器
- vue.runtime.xxx.js是运行版的Vue,只包含核心功能
- 因为使用runtime版本的vue可以提高效率但是不能解析模板,不能配置template配置对象,需要使用render函数去createElement创建元素
三、vue.config.js配置文件
- 可以使用
vue inspect > output.js
查看Vue脚手架的默认配置 - 使用vue.config.js可以对脚手架进行个性化定制,详情见: https://cli.vuejs.org/zh
四、ref属性
- 作用:被用来给元素或子组件注册引用信息(id的替代者),应用在html标签上获取的是真实的dom元素,应用在组件标签上获取的是组件实例对象(vc)
- 使用方式:
- 打标识
- 或者
- 获取:
this.$refs.xxx
五、配置项props
功能:让组件接收外部传过来的数据
-
传递数据:
-
接收数据:
-
第一种方式(只接收):
props:['name']
-
第二种方式(限制类型):
props: { name: type }
-
第三种方式(限制类型,是否必要,默认值)
props: { name: { type: required: default: } }
-
备注:
props是只读的,如果修改会被警告,当业务要求需要修改时,可以复制props的属性值到data中
props解析优先于data
六、mixin(混入)
-
功能:把多个组件共用的方法,配置,钩子等提取成一个混入对象
-
使用方式:
-
定义混入:
/*mixin.js*/ export const hunhe = { methods: { showName() { alert(this.name) }, mounted() { console.log('你好') } } }
-
使用混入:
Vue.mixin(name)全局混入 mixins:['name']局部混入
注意:
-
如果混合的data或methods发生冲突,那就以引入混合的文件为主
-
但是如果是生命周期钩子,就和本文件的合并,混合的钩子运行在前
-
七、插件
-
功能:用于增强Vue定义的js功能库
-
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
-
定义插件:
/*plugin.js*/ export default{ install(Vue, options) { //添加过滤器 Vue.filter() //添加全局指令 Vue.directive() //配置全局混入 Vue.mixin //添加实例方法 Vue.prototype.$myMethod = function() {...} Vue.prototype.$myProperty = xxx } }
-
使用插件:
//引入插件 import plugins from './plugins' //使用插件 Vue.use(plugins) //然后插件定义的过滤器,指令等等就可以直接使用了
八、scoped样式
-
作用: 让样式在局部生效,防止组件样式同名发生冲突
-
写法: 使用less格式的样式(需要安装less-loader)
总结TodoList案例
说明: 本案例不涉及总线,消息订阅,状态仓库
-
组件化编码流程:
-
拆分静态组件:组件要按照功能点拆分,命名不要和html元素冲突
-
实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用
-
如果是一个组件在用:放在组件本身即可
-
如果是一些组件在用:放在他们共同的父组件上(状态提升)
-
-
实现交互:从绑定事件开始,数据在哪改变数据的事件就在哪
-
-
props适用于
- 父组件 ==> 子组件通信
- 子组件 ==> 父组件通信 (要求父组件先传递给子一个函数)
注意:
-
使用v-model时不能绑定props传递过来的值,因为props不可修改
-
props传过来的如果是对象,修改对象里的属性Vue不会报错,但不推荐这么做
九、webStorage
包括:localStorage和sessionStorage
-
存储大内容大小一般支持5MB左右,不同浏览器可能不同
-
浏览器端通过
Windows.sessionStorage
和Windows.localStorage
属性来实现本地存储机制,存到硬盘上 -
相关API:(sessionStorage和localStorage身上的API一样,前几个字母就用xxx代替)
-
xxxxStorage.setItem('key', 'value')
: -
xxxxStorage.getItem('key')
-
xxxxStorage.removeItem('key')
-
xxxxStorage.clear()
-
备注:
- SessionStorage存储的内容会随浏览器窗口关闭而消失
- LocalStorage存储的内容,需要手动清除才会消失
xxxxStorage.getItem('key')
不存在相应的Key那么返回值是nullJSON.parse(null)
的值依然是null
十、组件的自定义事件
-
一种组件间通信的方式,适用于==子组件 > 父组件传递数据
父==>子 使用props最方便
-
使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
-
绑定自下定义事件:
-
第一种方式:在父组件中
<Demo @atguigu="callback/>"
或<Demo v-on:Demo="callback"/>
-
第二种方式:在父组件中
<Son ref="demo" /> 给子组件打上标识 ... mounted() { this.$refs.demo.$on('atguigu', this.callback) }
-
如果想让自定义事件触发一次可以用
@atguigu.once
或$once
方法
-
-
触发自定义事件:
this.$emit('atguigu', 数据)
-
解绑自定义事件:
this.$off('atguigu')
this.$off(['atguigu', 'demo'])
this.$off()
-
组件上也可以绑定原生的DOM事件,需要加上
native
修饰符
注意:通过
this.$refs.xxx.$on('atguigu', callback)
绑定自定义事件时,callback回调函数要么事先定义在methods中,要么用箭头函数,会有this指向问题十一、全局事件总线(GlobalEventBus)
-
一种组件间通信的方式,适用于任意组件间通信
-
安装全局事件总线
new Vue({ ... beforeCreate() { Vue.prototype.$bus = this //安装全局事件总线,$bus的值就是vm } ... })
-
使用事件总线:
- 接收数据:A组件想接收数据,在A组件中给$bus绑定自定义事件,事件的callback留在A组件自身
methods() { demo(value) { ... } } ... mounted() { // 给$bus绑定了一个xxx事件,一般是接收方去绑定事件,提供数据方去触发事件 this.$bus.$on('xxxx', this.demo) } beforeDestroy() { // 组件销毁前解绑事件 this.$bus.$off('xxx') }
- 提供数据:
this.$bus.$emit('xxx', 数据)
,找$bus
触发事件
注意:最好在beforeDestroy钩子中在组件销毁前,用$off去解绑当前组件所用的到的事件,因为
$bus
会一直存在不会随组件销毁而消失十二、消息订阅与发布
(不常用)组件间通信多用事件总线
-
一种组件间通信的方式,适用于任意组件间通信
-
使用步骤
-
安装pubsub(第三方库):
npm i pubsub-js
-
在使用的地方引入:
improt pubsub from 'pubsub-js'
-
接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
methods(){ demoCallback(msgName, value){...} } ... mounted() { // 每次订阅都会有独立的ID,销毁时需要用ID销毁 this.pid = pubsub.subscribe('xxx', this.demoCallback) //订阅消息 } beforeDestory() { // 取消订阅 pubsub.unsubscribe(this.pid) }
-
提供数据:
pubsub.publish('xxx', 数据)
-
最好在beforeDestory取消订阅
pubsub.unsubscribe(this.pid)
十三、nextTick
-
语法:
this.$nextTick(回调函数)
-
作用:在下一次DOM更新结束之后执行指定的回调函数
这里的下一次更新是指Vue在改变数据的时候并不会实时渲染模板更新DOM,但是如果想对渲染后DOM进行操作就需要在Vue渲染更新DOM后才有效
十四、Vue脚手架配置代理proxy
方法一
-
在vue.config.js中添加如下配置:
devServer: { proxy: 'http://localhost:5000' }
-
说明:
- 优点:配置简单,请求资源时直接发给前端8080即可
- 缺点:不能配置多个代理,不能控制是否走代理配置
- 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器(优先匹配前端资源)
方法二
-
编写vue.config.js配置具体代理规则:
module.exports = { devServer: { proxy: { // 请求如果带有/atguigu前缀就走代理服务器转发 '/atguigu': { target: 'http://localhost:5000', // 将请求重写,如果不重写会带着前缀,参数的key是一个正则匹配 pathRewrite: {'^/atguigu' : ''} // ws: true, // 用于支持websocket,默认为true // changeOrigin: true // 用于控制请求头的中的host值,默认为true }, '/demo': { target: 'http://localhost:5001', // 将请求重写,如果不重写会带着前缀,参数的key是一个正则匹配 pathRewrite: {'^/demo' : ''} }, } } } /* changeOrigin的值为true时,服务器收到的请求头host值为:localhost:5000 changeOrigin的值为false时,服务器收到的请求头host值为:localhost:8080 它的默认值为true,为了适应服务器屏蔽某些端口 */
-
说明
- 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
- 缺点:配置略微繁琐,请求资源时的url需要加前缀
十五、插槽
-
作用:在组件标签体当中插入
HTML结构
,可以让父组件可以向子组件指定位置插入HTML结构
,也是一种组件间通信的方式,适用于父组件===>子组件 -
分类:默认插槽、具名插槽、作用域插槽
-
使用方式:
-
默认插槽
App.vue父组件中: <Category> <div> html结构1 </div> </Category> 子组件中: <tempalte> <div> 定义插槽 <slot>插槽默认显示内容...</slot> </div> </tempalte>
说明:在父组件App.vue创建
组件标签,然后标签体里的HTML结构就会默认传递到子组件 的位置 -
具名插槽
父组件中: <Category> <template slot="center"> <div> html结构1 </div> </template> <template v-slot:footer> <div> html结构2 </div> </template> </Category> 子组件中: <tempalte> <div> 定义插槽 <slot name="center">插槽默认内容</slot> <slot name="footer">插槽默认内容</slot> </div> </tempalte>
给插槽起个名字,在传递结构的时候指定传递到哪个插槽
-
作用域插槽:
-
理解:可以用来把子组件的数据传递给父组件,同时子组件的结构就由父组件来决定
-
具体编码:
父组件: <Category title="游戏分类"> <!--scope属性用来接收组件内传递过来的所有数据作为一个对象--> <template scope="atguigu"> <ul> <li v-for="(g, index) in atguigu.games" :key="index">{{g}}</li> </ul> </template> </Category> <Category title="游戏分类"> <template scope="atguigu"> <h4 v-for="(g,index) in atguigu.games" :key="index">{{g}}</h4> </template> </Category> 子组件: <template> <div class="category"> <h3>{{title}}</h3> <!--定义一个插槽--> <slot :games="games">默认标签体2,没有指定标签填充就会出现</slot> </div> </template> <script> export default { name: "Category", props: ['title'], data() { return { games: ['红色警戒', '穿越火线', '超级玛丽'], } } } </script>
-
-
说明:前两种插槽的主要作用是由组件的使用者,向组件里传递HTML元素,
而作用域插槽是将子组件的数据传递回组件的使用者,也是作为组件间数据传递的一种方法
十六、Vuex
-
概念:在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中的多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
-
使用场景:多个组件需要共享数据时
-
搭建Vuex环境
- 创建文件:
src/store/index.js
//该文件用于创建Vuex中最为核心的store import Vue from 'vue' import Vuex from 'vuex' // 在这里使用vuex插件,因为脚手架对于import语句的处理 Vue.use(Vuex) //准备actions--用于响应组件中的动作 const actions = {} //准备mutations--用于操作数据(state) const mutations = {} //准备state--用于存储数据 const state = { sum: 0 } //创建store并暴露 export default new Vuex.Store({ actions, //配置对象和值重名可以用简写形式 mutations, state })
- 在
main.js
创建vm时传入store
配置项
import Vue from 'vue' import App from './App.vue' // 引入store import store from './store' Vue.config.productionTip = false const vm = new Vue({ el: '#app', render: h => h(App), store: store, beforeCreate() { Vue.prototype.$bus = this } }) console.log('vm', vm)
注意:
-
因为vue脚手架会把所有import语句按顺序放在最前面执行,所以如果在
main.js
文件当中import store from './store'
时Vue.use(Vuex)
还没生效会报错 -
在组件当中读取vuex中的数据:
$store.state.xxx
-
在组件当中修改vuex中的数据:
$store.dispatch('action中的方法名', 数据)
或者$store.commit('mutation中的方法名', 数据)
-
备注:如果没有网络请求或者业务逻辑处理,组件中可以越过
actions
,直接commit
有业务逻辑写到action当中,有context参数调用上下文很方便
- 创建文件:
-
getters配置项的使用
-
概念:当state中的数据需要经过加工后再使用时,可以使用getter,主要应用在加工逻辑复杂并且需要复用的场景下
-
在
store.js
中追加getters配置.... const getters = { // 这里可以收到state参数 bigSum(state) { // 假如这是一个复杂的逻辑 return state.sum * 10 } } .... //创建store并暴露 export default new Vuex.Store({ actions, //配置对象和值重名可以用简写形式 mutations, state, getters })
-
在组件当中读取数据
$store.getters.xxx
-
Vuex中四个map方法的使用
-
mapState
方法:用于帮助我们映射state
中的数据为计算属性import {mapState, mapGetters} from 'vuex' ... computed: { // 借助mapState生成计算属性,从state中读取数据填充到computed对象当中 (对象写法) ...mapState({he: 'sum', xuexiao: 'school', xueke: 'subject'}), // 借助mapState生成计算属性,从state中读取数据填充到computed对象当中 (数组写法) ...mapState(['sum', 'school', 'subject']), }
-
mapGetter
方法:用于帮助我们映射getters
中的数据为计算属性import {mapState, mapGetters} from 'vuex' ... computed: { // 借助mapGetters生成计算属性,从state中读取数据填充到computed对象当中 (对象写法) ...mapGetters({bigSum: 'bigSum'}) // 借助mapGetters生成计算属性,从state中读取数据填充到computed对象当中 (数组写法) ...mapGetters(['bigSum']) }
-
mapActions
方法:用于帮助我们生成与actions
对话的方法,即:包含$store.dispatch(xxx)
的函数import {mapState, mapGetters, mapActions, mapMutations} from 'vuex' ... methods: { ...mapActions({incrementOdd: 'jiaOdd', incrementWait: 'jiaWait'}) ...mapActions(['jiaOdd', 'jiaWait']) }
-
mapMutations
方法:用于帮助我们生成mutations
对话的方法,即:包含$store.commit(xxx)
的函数import {mapState, mapGetters, mapActions, mapMutations} from 'vuex' ... methods: { ...mapMutations({increment: 'JIA', decrement: 'JIAN'}) ...mapMutations(['JIA', 'JIAN']) }
-
-
模块化+命名空间
-
目的:让代码更好维护,让多种数据分类更加明确,避免所有的状态和动作都放在一起
-
修改
store.js
const personOptions = { namespaced: true, //开启命名空间,用map方法时就能识别到 actions: { }, mutations: { }, state: { }, getters: { } } const countAbout = { namespaced: true, //开启命名空间,用map方法时就能识别到 actions: { }, mutations: { }, state: { }, getters: { } } const store = new Vuex.Store({ modules: { countAbout, personAbout } })
提示:可以把模块化后的配置选项作为单独的js文件放到store文件夹中,再引入
-
开启命名空间后,组件中读取
state
数据://方式一:直接读取 this.$store.state.personAbout.personList //方式二:用mapstate读取 ...mapState('countAbout', ['sum','school','subject']) ,
-
开启命名空间后,组件中读取
getters
数据://方式一:直接读取 (getter的命名方式与其他配置项不太一样) this.$store.getters['personAbout/firstPersonName'] //方式二:借助mapGetters读取 ...mapGetters('countAbout', ['bigSum'])
-
开启命令空间后,组件调用
dispatch
//方式一: 自己直接dispatch this.$store.dispatch('personAbout/addPerson', person) //方式二:借助mapActions ...mapActions('countAbout', {incrementOdd: 'jiaOdd', incrementWait: 'jiaWait'})
-
开启命名空间后,组件调用
commit
//方式一:自己直接commit this.$store.commit('personAbout/ADD_PERSON', person) //方式二:借助mapMutations ...mapMutations('countAbout', {increment: 'JIA', decrement: 'JIAN'})
-
十七、路由
- 理解:一个路由(route)就是一组映射关系(key-value), 多个路由需要路由器(router)进行管理
- 前端路由:key是路径,value就是组件。
基本使用
-
安装vue-router:
npm i vue-router
-
应用插件:
Vue.use(VueRouter)
-
编写router配置项:
//引入VueRouter import VueRouter from "vue-router"; import About from "@/components/About"; import Home from "@/components/Home"; //创建router实例对象,去管理路由规则 const router = new VueRouter({ routes: [ { path: '/about', component: About }, { path: '/home', component: Home } ] }) export default router
-
用
router-link
标签实现触发路由切换<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
-
用
router-view
指定组件展示位置<router-view></router-view>
几个注意点
- 需要被切换的路由组件通常存放在
pages
文件夹,静态展示的一般组件通常存放在components
文件夹 - 通过切换,”隐藏“了的路由组件,默认是被销毁掉的,需要的时候再去挂载
- 每个组件都有款自己的
$route
属性,里面存储着自己的路由信息 - 整个应用只有一个
router
,可以通过组件的$router
属性获取 - 每个路由组件都会有
$route
和$router
属性,前者是存储自己的路由信息,后者是同一个属性对象公共同的路由器
多级路由
-
配置路由规则,使用children配置顶
const router = new VueRouter({ routes: [ { path: '/about', component: About, }, { path: '/home', component: Home, children: [ { path: 'news', // 底层监测到子路由时会自动加上/ component: News }, { path: 'message', component: Message } ] } ] })
-
跳转要写完整的路由路径
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
tip: children里配置的子路由,如果被访问那么就会被渲染到上一级组件中的
标签的位置
路由的
query
参数-
传递参数
<!--跳转路由并携带query参数,to的字符串写法--> <router-link :to="`/home/message/detail?id=${message.id}&title=${message.title}`">{{message.title}}</router-link> <!--跳转路由携带query参数,对象写法--> <router-link :to="{ path: '/home/message/detail', query: { id: message.id, title: message.title } }"> {{message.title}} </router-link>
-
接收参数
$route.query.id $route.query.title
命名路由
-
作用:可以简化路由的跳转,在路径复杂的情况
-
如何使用
-
给路由命名:
{ name: 'guanyu', path: '/about', component: About, },
-
简化跳转
简化前 <router-link class="list-group-item" active-class="active" :to="/demo/test/about">About</router-link> 简化后 <router-link class="list-group-item" active-class="active" :to="{name: 'guanyu'}">About</router-link> <router-link :to="{ name: 'guanyu', query: { id: 666, title: '你好' } }" 跳转<router-link/>
-
路由的
params
参数-
配置路由,声明接收params参数占位符
{ path: 'message', component: Message, children: [ { name: 'xiangqing', path: 'detail/:id/:title', //使用占位符声明接收params参数 component: Detail } ] }
-
传递参数
<!-- 跳转携带params参数,to的字符串写法 --> <router-link :to="`/home/message/detail/${message.id}/${message.title}`">{{message.title}}</router-link>   <!-- 跳转携带params参数,to的字符串写法 --> <!--跳转路由携带query参数,对象写法--> <router-link :to="{ path: '/home/message/detail', // name: 'xiangqing', params: { id: message.id, title: message.title } }"> {{message.title}} </router-link>
注意:路由携带params参数时,如果使用to的对象写法则不能使用path配置项,必须和name配置项搭配使用
-
接收参数
$route.params.id $route.params.title
路由的props配置项
-
作用:让路由组件更方便地收到参数,在代码逻辑当中不用去
$route.query.xxx
或$route.params.xxx
调用属性//props的第一种写法,值为对象,该对象中的所有key-value都会以pros形式传给Detail组件。用的很少 props: { a: 1, b: 'hello', } //props的第二种写法,配置为true把该路由组件收到的所有params参数以props的形式传给Detail组件 props: true //props的第三种写法,值为函数,可以把return的key-value值以props的形式传递给Detail组件 props: function ($route) { return { id: $route.query.id, title: $route.query.title } }
<route-link>
的replace属性-
作用:控制路由跳转时操作浏览器历史记录的模块
-
浏览器历史记录以栈的方式存储,有个指针指向栈顶也就是当前页面;有两种写入方式:
push
和replace
,push是往栈顶追加历史记录,replace是替换掉当前的记录,路由跳转时默认为push -
如何开启
replace
模式:<router-link replace class="list-group-item" active-class="active" to="/home">Home</router-link>
编程式路由导航
-
作用:不借助
<router-link>
标签实现路由跳转,让路由跳转更加灵活可以用别的标签再利用事件进行触发 -
具体编码:
// 利用$router的两个api实现路由跳转: push,replace methods: { pushForward(message) { this.$router.push({ name: 'xiangqing', query: { id: message.id, title: message.title } }) }, replaceForward(message) { this.$router.replace({ name: 'xiangqing', query: { id: message.id, title: message.title } }) } } this.$router.forward() //前进 this.$router.back() //后退 this.$router.go(-1) // 前进或后退几步
缓存路由组件
-
作用:让不展示的组件保持挂载不被销毁
-
具体编码:
<keep-alive include="News"> <router-view></router-view> </keep-alive>
include属性控制的是展示在这个位置的组件中具体要缓存哪个组件,如果不配置就缓存所有展示到
的组件
两个新生命周期钩子
- 作用:用于捕获路由组件的激活状态,路由组件独有,可以用在需要缓存组件的同时开启或停掉组件的一些工作
- 具体名字
activated
路由组件被激活时触发deactivated
路由组件失活时触发
路由守卫
-
作用:对路由进行权限控制
-
分类:全局守卫、独享守卫、组件内守卫
-
全局守卫
// 全局前置路由守卫---初始化时被调用、每次路由切换之前被调用,拦截所有的路由切换请求 router.beforeEach((to, from, next) => { console.log('前置路由守卫',to, from) if (to.meta.isAuth) { //判断是否需要进行权限控制 if (localStorage.getItem('school') === 'atguigu') { //权限控制的具体规则 // 满足条件放行 next() } else { alert('学校名不对,无权查看') } } else { next() } }) // 全局后置路由守卫---初始化时被调用、每次路由切换之后被调用,用的不多可以做一些收尾工作 router.afterEach((to, from) => { console.log('全局后置路由守卫', to, from) if (to.meta.title) { document.title = to.meta.title //修改网页的title } else { document.title = 'vue_test' } })
-
独享守卫:组件独有的守卫配置
// 作为一个路由组件配置项 { name: 'xinwen', path: 'news', // 底层监测到子路由时会自动加上/ component: News, meta: {isAuth: true, title: '新闻'}, beforeEnter: (to, from, next) => { console.log('独享前置路由守卫', to, from) if (to.meta.isAuth) { if (localStorage.getItem('school') === 'atguigu') { // 满足条件放行 next() } else { alert('学校名不对,无权查看') } } else { next() } } }
-
组件内守卫
// 进入守卫:通过路由规则,进入组件之前被调用 beforeRouteEnter(to, from, next) { } // 离开守卫:通过路由规则,即将离开该组件时被调用 beforeRouteLeave(to, from, next) { } /* 这两个守卫可以写一些该路由组件独有的逻辑 */
注意:要和前置、后置路由守卫区分开,后置路由守卫是切换进入组件之后的后置操作
-
路由器的两种工作模式
- 路由器的hash模式:
- 兼容性好,适配绝大多数浏览器
- 地址中永远带着#号,不美观。
- 若以后将地址通过第三方手机app分享,若app校验严格,地址会被标识为不合法
- history模式:
- 地址干净,美观不带#号
- 兼容性和hash模式相比略差
- 应用部署上线时需要后端人员支持,解决刷新页面时将/资源后的字符都当成请求参数造成服务端404的问题
- 对于一个url来说,什么是hash值?----- #及其后面的内容就是hash值。
- hash值不会包含在HTTP请求中即hash值不会带给服务器。
十八、Element UI使用
基本使用
-
npm安装
npm i element-ui -S
-
引入组件库
-
全局引入(不推荐)
import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue'; Vue.use(ElementUI);
-
按需引入
借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。
-
npm install babel-plugin-component -D
-
修改
babel.config.js
文件{ "presets": [["es2015", { "modules": false }]], "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }
-
引入需要的组件
import { Button, Select } from 'element-ui'; import App from './App.vue'; Vue.component(Button.name, Button); Vue.component(Select.name, Select); /* 或写为 * Vue.use(Button) * Vue.use(Select) */
如果在这里出现问题可以去babel-plugin-component的github找到与当前脚手架相匹配的配置信息
-
-
去Element UI官网复制粘贴需要的组件就能使用了
注意:按需引入组件不需要额外引入组件的样式,相关的样式会自动导入
-
修改样式
-
修改全局样式
- 新建全局样式表
新建 global.css 文件,并在 main.js 中引入。 global.css 文件一般都放在 src->assets 静态资源文件夹下的 style 文件夹下,在 main.js 的引用写法如下:
import "./assets/style/global.css";
在 global.css 文件中写的样式,无论在哪一个 vue 单页面都会覆盖 ElementUI 默认的样式。
适合于对elementUI整体的修改,比如整体配色的修改;
-
修改单个组件样式
- 使用 /deep/,前面为修改组件类名的父级组件样式类名,后面为修改组件的类名,里面是样式的修改element ui组件默认class就是标签名
.dialogPage /deep/ .el-dialog { margin-left: 20px !important; }
/deep/ 的方式可以很方便的在vue组件中修改默认样式,也不会于其他页面有冲突。
- 在当前的vue单页面的
<style>
标签后,添加一对新的<style>
标签,新的<style>
标签中不要添加scoped
属性。这样就会覆盖element ui原来的样式
<style scoped> .left { padding-top: 25px; } </style> <style> .left { background-color: red; } </style>
注意:这样实际是修改了全局的样式,同class名的都被影响会引发冲突
属性和事件
Element UI
有很多自定的属性和事件,可以用来传递数据修改配置及事件响应- 属性在每个组件的下面
Attributes
有介绍,可以通过v-bind
也就是:
去把自己定义的数据传递给组件 - 事件在每个组件的下面
Events
中有介绍,可以通过v-on
也就是@
去绑定这个事件,当触发了这个事件可以去执行相应的回调 - 有些组件身上也有特殊的方法,比如表单
form
对应的就有validate
方法用于校验整个表单是否符合规范,当收集到这个组件的对象时就可以使用这个方法,方法可以在Methods中找到
- 属性在每个组件的下面
-