前言
最近发现 vue 某些用得少的知识点或者某些深入的理解方面 有时候会因为记忆不深刻而遗忘掉。所以特开此贴记录一下vue相关的易忘点及一些对vue的深入思考。
记录
- 使用vue-cli 3.x版本搭建vue项目过程
// 以下命令行终端输入
// Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+)
// 全局安装vue-cli脚手架
npm install -g @vue/cli
// 创建一个新vue项目(注意项目名称不能有大写字母)
vue create vue-test
? Check the features needed for your project: (Press to select, to toggle all, to invert selection)
// 检查项目所需的功能:(按选择,切换所有,反转选择)
( ) TypeScript // 支持使用 TypeScript 书写源码
( ) Progressive Web App (PWA) Support // PWA 支持
( ) Router // 支持 vue-router
( ) Vuex // 支持 vuex
( ) CSS Pre-processors // 支持 CSS 预处理器。
( ) Linter / Formatter // 支持代码风格检查和格式化。
( ) Unit Testing // 支持单元测试。
( ) E2E Testing // 支持端到端测试
// 我这里选择第二项自定义配置一些东西并创建完成(第一次创建建议默认)
// 接下来进入创建好的vue项目
cd vue-test
// 运行初始项目
npm run serve
- v-once指令
使用v-once 只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
通过使用 v-once 指令,能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定。
<template>
<div class='vOnce-content'>
<span v-once>渲染一次之后不会改变:{{ msg }}</span><br />
<span>没有设置v-once属性:{{ msg }}</span><br />
<button @click="changeMsg">改变Msg</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: '内容'
}
},
methods: {
changeMsg () {
this.msg = '改变后内容'
}
}
</script>
用法:可以通过 v-once 创建低开销的静态元素或组件
- 一些指令缩写及汇总
v-on —— @ 事件绑定
v-bind —— : 属性绑定
v-slot —— # 插槽
v-model —— 表单双向数据绑定
v-if —— 判断语句
v-else —— 判断语句(和v-if配合使用)
v-show —— 是否显示(和v-if区别在于始终渲染dom树)
v-for —— 渲染数组的循环语句
v-html —— 渲染为html模版
v-text —— 渲染文本(不渲染为html模版)
v-cloak —— 防止页面闪烁
- 一些修饰符总结
事件修饰符:
<!-- .stop阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- .prevent阻止默认事件(这里指提交事件不再重载页面) -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- .capture添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- .self只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
按键修饰符:
<!-- .enter只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
// 类似的有
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
<!-- .exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。 -->
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>
// 鼠标按钮修饰符
.left
.right
.middle
.sync 修饰符:
在一个包含 title prop 的组件中,可以用以下方法表达对其赋新值的意图:
this.$emit('update:title', newTitle)
然后父组件可以监听那个事件并根据需要更新一个本地的数据属性。例如:
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
为了方便起见,我们为这种模式提供一个缩写,即 .sync 修饰符:
<text-document v-bind:title.sync="doc.title"></text-document>
表单中修饰符:
.lazy
在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
<input v-model.number="age" type="number">
这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
<input v-model.trim="msg">
- 当在组件上添加class属性时会将其添加到到组件里的根元素节点上
- 用 key 管理可复用的元素
// 如下给input元素添加key指定唯一值,当切换显示时input会重新渲染(即输入框内容会重置),而其他元素则会高效复用(vue复用的特性)
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
- v-if和v-for不要一起使用
原因:v-for比v-if优先,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候
- Vue.set用法
由于 JavaScript 的限制
Vue 不能检测对象属性的添加或删除,Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项的值时
当你修改数组的长度时
Vue.set(object, key, value) 或者 vm.$set(object, key, value)
// 第一个参数是所要修改的对象或数组,第二个参数为修改的索引或键名,第三个参数为修改的值
// 例子:
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
},
items: ['a', 'b', 'c']
}
})
// 使用Vue.set添加一个新属性
Vue.set(vm.userProfile, 'age', 27)
Vue.set(vm.items, 1, d)
// 扩展:
// 使用Object.assign()增添属性
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
Object.assign()方法:
Object.assign(target, …sources) 此方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
由上例可知是将vm.userProfile对象及 {age: 27,favoriteColor: ‘Vue Green’}新对象复制到空对象{}里
- slot相关
具名插槽:
// <slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
// 一个不带 name 的 <slot> 出口会带有隐含的名字“default”
// 在向具名插槽提供内容的时候,以 v-slot 的参数的形式提供其名称
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
- 动态组件上使用 keep-alive
保持组件的状态,避免反复重渲染
即组件切换之前所停留的页面,返回到此时还是那个页面,防止组件失活
- 异步组件
详解 vue官网此处
- 处理边界情况
$root 访问根节点
$parent 访问父组件
$refs 访问子元素(配合ref使用)
依赖注入:(可以把依赖注入看作一部分“大范围有效的 prop”)
provide 指定我们想要提供给后代组件的数据/方法
inject 在任何后代组件里,使用 inject 选项来接收指定的我们想要添加在这个实例上的属性
实际处理过程中使用这些来处理边界情况的话会增加代码的耦合度,使未来的代码重构变得困难,因此基本使用vuex来管理这些状态。
- 程序化的事件侦听器
(注:通常不会用到这些,但是当需要在一个组件实例上手动侦听事件时,就可以用上)
通过 $on(eventName, eventHandler) 侦听一个事件
通过 $once(eventName, eventHandler) 一次性侦听一个事件
通过 $off(eventName, eventHandler) 停止侦听一个事件
具体了解 点击此处
- vue中组件name的作用
(因为写组件时用到的name次数很少,所以探究一下name的作用)
1.当项目使用keep-alive时,可搭配组件name进行缓存过滤
2.DOM做递归组件时
3.当你用vue-tools时
————————————————————————————————
因为有文章总结的很详细,所以详细了解请 点击此处
- Vue的生命周期钩子函数之activated的理解
activated():在vue对象存活的情况下,进入当前存在activated()函数的页面时,一进入页面就触发;可用于初始化页面数据等
- activated 生命周期在keep-alive 组件激活时调用
- 服务器端渲染期间不调用该生命周期
- 通常和deactivated周期一起使用
与created及mounted等生命周期钩子函数的比较:
created是创建vue实例时的钩子函数
mounted是挂载vue实例后的钩子函数
activated是组件被激活后的钩子函数
created():在创建vue对象时,当html渲染之前就触发;但是注意,全局vue.js不强制刷新或者重启时只创建一次,也就是说,created()只会触发一次;
————————————————
mounted():在主页挂载时执行一次,如果没有缓存的话,再次回到主页时,mounted还会执行,从而导致ajax反复获取数据。
————————————————
activated():不受缓存的影响,每次重新回到主页都会执行。在vue对象存活的情况下,进入当前存在activated()函数的页面时,一进入页面就触发;可用于初始化页面数据等.
- Vue中v-model的理解
v-model相当于是用v-bind和v-on结合起来使用的一种语法糖
// 即以下
<Input v-model="searchText">
// 等价于
<Input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
- 解决组件之间的循环引用问题
(使用模块系统依赖/导入组件时可能产生的问题)
错误提示为:
Failed to mount component: template or render function not defined.
解决方法:
// 生命周期钩子 beforeCreate 时注册
beforeCreate: function () {
this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default
}
// 或者在本地注册组件的时候,使用 webpack 的异步 import
components: {
TreeFolderContents: () => import('./tree-folder-contents.vue')
}
- 过渡< transition >及< transition-group >基本使用
过渡类名变化过程:
transition例子:
<template>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
</template>
<script>
export default {
name: 'demo',
data () {
return {
show: true
}
}
</script>
<style lang='less' scoped>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
</style>
transition标签中的name中定义的什么,那类名就以什么开头再跟上-enter-active或-leave-active,如果未定义name,则v- 是这些类名的默认前缀。
(如上例中name定义为fade,则类名为fade-enter-active)
官方类名释义:
v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to: Vue的2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
————————————————————————————————
v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to: Vue的2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
过渡模式:
in-out:新元素先进行过渡,完成之后当前元素过渡离开。
out-in:当前元素先进行过渡,完成之后新元素过渡进入。
< transition-group >使用请参照官网此处
(保留日后总结)
ps:过渡好像能做很多有意思的东西,引用官网过渡最后一句话
- filter过滤器的使用
// 过滤器用在两个地方:双花括号插值和 v-bind 表达式
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
例子:
<template>
<div class='filter'>
<input type="text" v-model="myValue">
<p>{{ myValue|capitalize|capitalizeLast }}</p>
</div>
</template>
<script>
export default {
data () {
return {
myValue: ''
}
},
// 首字母大写
filters: {
capitalize (value) {
if (value) {
value = value.toString()
var newValue = value.charAt(0).toUpperCase() + value.slice(1)
return newValue
} else {
return ''
}
},
// 尾字母大写
capitalizeLast (value) {
if (value) {
value = value.toString()
var newValue = value.slice(0, value.length - 1) + value.charAt(value.length - 1).toUpperCase()
return newValue
} else {
return ''
}
}
}
}
</script>
上例实现了输入后的首尾字母大写。其中使用两个过滤器,第一个过滤器实现首字母大写,第二个过滤器获得第一个过滤后的值之后再实现尾字母大写
- Vue数据双向绑定的响应式原理
Vue采用的是数据劫持与发布订阅相结合的方式实现双向绑定
数据劫持主要就是利用
Object.defineProperty()
这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现
发布订阅模式需要如下来实现
Observer 监听器:用来监听属性的变化通知订阅者
Watcher 订阅者:收到属性的变化,然后更新视图
Compile 解析器:解析指令,初始化模版,绑定订阅者
详细了解点击此处