1、vue中的环境变量调整
假如需要添加第三种模式的时候,或者在开发过程中需要添加环境变量的时候,那么就需要做如下配置
先在根目录下添加.env.自定义名字,并且里面的内容模式可以如上图进行配置
"scripts": { "dev": "vue-cli-service serve --mode unit", "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" },
在package.json文件中添加dev模式的,并且--mode后指定需要指定的模式
这需要就可以在项目中使用process.env进行访问
2、优雅更新props
更新 prop
在业务中是很常见的需求,但在子组件中不允许直接修改 prop
,因为这种做法不符合单向数据流的原则,在开发模式下还会报出警告。因此大多数人会通过 $emit
触发自定义事件,在父组件中接收该事件的传值来更新 prop
。
常规做法:
child.vue:
parent.vue:
这种做法没有问题,我也常用这种手段来更新 prop
。但如果你只是想单纯的更新 prop
,没有其他的操作。那么 sync
修饰符能够让这一切都变得特别简单。
相当于语法 @update:属性名 = “value => this.属性名=value”
使用div里的contenteditable属性来模拟v-model
<template> <div class="container"> <div>{{text}}</div> <div contenteditable="true" v-html="isLock? copyTxt: text" @input="inputEvent" @focus="focusEvent" @blur="isLock = false"></div> <el-button type="primary" @click="changeEvent">按钮</el-button> </div> </template> <script> export default { name: 'home', data () { return { text: 'this is text', copyTxt: this.text, isLock: false } }, methods: { inputEvent (ev) { this.text = ev.target.innerText }, focusEvent () { this.copyTxt = this.text this.isLock = true }, changeEvent () { this.text = 'are you ok???' } } } </script> <style lang="less" scoped></style>
注意:在通信的过程中,如果存在父组件,子组件, 孙组件,那么孙组件想修改父组件中的属性,那么可以调用this.$parnet.$emit('函数名', 属性值),当然前提要父组件监听该方法,所以注重$parent, $children的使用
3、provide/inject 的使用
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。
简单来说,一个组件将自己的属性通过 provide
暴露出去,其下面的子孙组件 inject
即可接收到暴露的属性。
4、小型状态管理器
大型项目中的数据状态会比较复杂,一般都会使用 vuex
来管理。但在一些小型项目或状态简单的项目中,为了管理几个状态而引入一个库,显得有些笨重。
在 2.6.0+ 版本中,新增的 Vue.observable
可以帮助我们解决这个尴尬的问题,它能让一个对象变成响应式数据:
5、卸载watch观察
通常定义数据观察,会使用选项的方式在 watch
中配置:
6、过滤器的复用
过滤器被用于一些常见的文本格式化,被添加在表达式的尾部,由“管道”符号指示。
7、render函数的使用
入门案例
render (h) { return h('div', 'this is test') }
延伸案例, 实现多插槽
render (h) { return h('div', [this.$slots.title, this.$slots.content]) }
render (h) { return h('div', [ { tag: 'div', children: [h('span', { domProps: { innerHTML: 'haha' } })] }, this.$slots.title, this.$slots.content ]) }
使用option进行配置
render (h) { return h('div', { class: { // 表示注入动态类名 item_container: true }, staticClass: 'abc', // 注入静态类名 style: { // 表示注入style样式 color: 'red', 'font-weight': 'bold', cursor: 'pointer' }, ref: 'myRef', // 表示注入的ref选项,以便获取元素 attrs: { // 设置标签上的属性 'data-id': 'my-id' }, on: { // 绑定事件 click: this.clickEvent }, // 仅用于组件,用于监听原生事件,而不是组件内部使用 // `vm.$emit` 触发的事件。 // nativeOn: { // click: this.clickEvent // }, domProps: { innerHTML: '这个是标题', value: 'inputValue' // 这个是输入框中的value值 } }) }
第三个参数可以实现多插槽
render (h) { return h('div', { staticClass: 'abc' }, [this.$slots.title, this.$slots.content]) }
render (h) { return h('div', [ { tag: 'div', children: [h('span', [this.$slots.title, this.$slots.content])] } ]) }
注意:通常来讲,在虚拟dom中不使用指令,元素的构成可以使用js进行拼接
8、属性传值过程中,批量传值的方法
如果存在多重组件嵌套的时候,父组件通过传值的方式向子组件传递属性,但是子组件没有使用,需要全部传递给孙组件,那么这个时候就可以使用以下方法进行传值
父组件
<template> <div class="container"> <content-item name="aaa" age="20" sex="1" @changeEvent="changeEvent"></content-item> </div> </template> <script> import contentItem from './contentItem' export default { name: 'home', components: { contentItem }, methods: { changeEvent () { console.log('this is parent changeEvent', arguments) } } } </script> <style lang="less" scoped></style>
注意:如果父组件传值给子组件,但子组件没有接收的话,那么这些属性会显示在节点树上,如果接收了则不会显示在节点树上,这时候如果不需要其显示在节点树上,那么就可以在子组件中添加属性 inheritAttrs: false,这样就会显示在节点树上
子组件
<template> <div> <span>this is conentItem</span> <item v-bind="{...$attrs, 'haha': 'ok'}" v-on="$listeners"></item> <!--这样就可以在子组件不接收的情况下传递给孙组件--> <!-- 这种情况也可以传递事件--> </div> </template> <script> import item from './item' export default { name: 'contentItem', components: { item }, inheritAttrs: false // 不显示在节点树上 } </script> <style lang="less" scoped></style>
注意:这种情况记得使用v-bind与v-on,以及关键字$attrs, $listeners
孙组件
<template> <div> <div @click="changeEvent">{{$attrs}}</div> </div> </template> <script> export default { name: 'item', methods: { changeEvent () { console.log('ok') this.$emit('changeEvent', 'haha') // 这样直接这种就可以传递值到根组件上 console.log(this.$listeners) // 也可以通过这种方式访问 } } } </script> <style lang="less" scoped></style>
注意:孙组件里的$attrs是表示父组件还没有使用的属性,不包含已使用的属性 ,相当于用一个少一个
9、v-model实现多选的情况
v-model如果遇到checkbox需要进行多选的时候,这个时候把v-model对应的data里的值改成数组,就可以实现多值的选择
<template> <div class="container"> <label><input type="checkbox" v-model="checkList" value="语文">语文</label> <label><input type="checkbox" v-model="checkList" value="英语">英语</label> <label><input type="checkbox" v-model="checkList" value="数学">数学</label> <label><input type="checkbox" v-model="checkList" value="历史">历史</label> <ul> <li v-for="val of checkList" :key="val">{{val}}</li> </ul> </div> </template> <script> export default { name: 'Home', data () { return { checkList: [] } } } </script>
10、自定义指令的使用
自定义指令有分为全局指令与局部指令,全局指令注册完成后,那么就可以在整个项目中使用, 局部指令则只在指定的页面或者组件中使用
入门案例
import Vue from 'vue' export const install = vue => { vue.directive('bill', (el, binding, vnode) => { console.log(el, binding, vnode) }) } Vue.use(install) // 通过use来进行全局指令的注册
自定义指令的生命周期函数有:
-
bind
: 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
: 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 -
update
: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
-
componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。 -
unbind
: 只调用一次,指令与元素解绑时调用。
声明的两种方式
// vue.directive('bill', { // bind () { // console.log('bind', arguments) // }, // inserted () { // console.log('inserted', arguments) // }, // update () { // console.log('update', arguments) // }, // componentUpdated () { // console.log('componentUpdated', arguments) // }, // unbind () { // console.log('unbind', arguments) // } // })
vue.directive('bill', (...rest) => { console.log(rest) })
注意:如果自定义指令中有一个函数的时候,那么这个函数相当于bind使用
11、computed与methods的区别
computed与methods的区别在于,前者在基于Object.defineProperty实现在,也就是当节点数据刷新的时候,computed里的值如果有发生变化,那么对应的函数会被调用,如果没有变化,会调用缓存里的数据,则不会发生变化 ,而后者无论是否变化,当节点刷新时都会被调用