Vue中文文档,重点摘录
-
虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。
-
所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 (一些根实例特有的选项除外)。
-
一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
值得注意的是: 只有当实例被创建时就已经存在于 data 中的 property 才是响应式的。 -
模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math 和 Date 。你不应该在模板表达式中试图访问用户定义的全局变量。
全局变量的一个白名单包括: 'Infinity,undefined,NaN,isFinite,isNaN,' 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' 'require' -
修饰符
修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。 例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault(): -
CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case)
-
所有的.vue文件由三部分组成template,script,style,分别包含了组件的模板、脚本、样式.
-
Vue组件中的data必须是函数
Object是引用数据类型,每个组件的data都是同一个内存地址,一个数据改变了其他数据也改变了;当我们的data是一个函数时,每一个实例的data属性都是独立的,不会相互影响了。 -
在给子组件传递数据的时候,最好先在data中声明属性,然后传递属性,防止使用修饰符时出现无效和其他bug.
Vue的创建
一个简单的 Vue 实例只需要四步即可 创建vue实例
数据与方法
改变data属性,视图刷新的条件
声明周期函数示意图
声明周期函数示意图
Vue.nextTick()作用
语法: this.$nextTick( [callback] )
作用: 将回调延迟到下次 DOM 更新循环之后执行callback函数。
new Vue({
// ...
methods: {
// ...
example: function () {
// 修改数据
this.message = 'changed'
// DOM 还没有更新
this.$nextTick(function () {
// DOM 现在更新了
// `this` 绑定到当前实例
this.doSomethingElse()
})
}
}
})
模板语法-插值表达式
- 正确用法
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
- 错误用法
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
// 赋值语句,也不是表达式(假如a是data中的属性)
{{ a=2 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
计算属性缓存 vs 方法
对于任何复杂逻辑,都应当使用计算属性;因为计算属性有缓存机制,重复调用会返回缓存.方法每次都会执行函数体中的操作,增加性能损耗.我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。如果使用方法,会多次执行函数增加性能损耗.
//注意:
//计算属性now将不再更新,因为 Date.now() 不是响应式依赖:
computed: {
now: function () {
return Date.now(); //非响应式依赖,不会缓存
},
reversedMessage: function () {
return this.message.split('').reverse().join(''); //响应式依赖,会缓存
}
}
计算属性 vs 侦听属性
当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch.通常更好的做法是使用计算属性而不是命令式的 watch 回调。Demo演示
<div id="demo">{{ fullName }}</div>
//监听属性
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
//计算属性
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
- 侦听器的优点
计算属性和侦听器都可以响应数据的变化, 但当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
计算属性的setter
- 计算属性默认只有 getter,不过在需要时你也可以提供一个 setter: Demo
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
Class与Style绑定
- class与style绑定的类型可以是: 字符串、对象、数组
- 字符串时,可以传递表达式,根据条件显示对应的样式
- 对象时,可以传递data中的property, 也可以传递methods中的方法,还可以传递computed中的计算属性.
- 数组时, 可以传递多个对象(万物皆对象) 子组件样式优先级大于父组件
v-if、v-show、v-for
使用v-if、v-else、v-else-if的时候, 可以用key来管理可复用的元素
注意,v-show 不支持 <template> 元素,也不支持 v-else。
v-if是真正的渲染, 它会确保在切换条件过程中,块内的元素的事件监听器和子组件适时的销毁和重建; v-show只是简单的切换css.
v-if的切换开销大, v-show则是初始渲染开销大,频繁切换使用v-show, 运行时经常改变则使用v-if.
v-if和v-for一起使用时, v-for的优先级更高, 会导致无论v-if是否为ture,都会遍历整个循环.
v-for遍历时,可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:
<div v-for="item of items"></div>
在 v-for 里使用值范围
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
//结果: 1 2 3 4 5 6 7 8 9 10
v-for和<template>搭配可减少渲染次数
v-for和自定义组件使用时,需要使用props来传递值
在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。
不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。
2.2.0+ 的版本里,当在组件上使用 v-for 时,key 现在是必须的。
v-for可遍历数组,第一个参数是obj,第二个参数是索引(index)
v-for可遍历对象,第一个参数是value,第二个参数是key,第三个参数是索引.
遍历对象,一个参数时,会输出对象中的value
sexDict: {boy: '男',}
<div v-for="sex in sexDict" :key="sex">
{{sex}} //结果为"男"
</div>
尽可能为遍历元素加上key,获得渲染优化.(Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。)
//label会高度复用,input因为设置了不同的key所以不会被复用,每次切换loginType的时候,块内元素都会被重新销毁和创建.
<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>
在 <template> 元素上使用 v-if 条件渲染分组, 最终的渲染结果将不包含 <template> 元素。
v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
数组
- Demo参考组件 component/array.vue
-
数组变异方法: push/pop/unshift/shift/splice/sort/reverse改变原始数组
-
数组非变异方法: filter/concat/slice不改变原始数组,总是返回新数组
对于对象来说:
1, Vue只能检测初始化时data中对象的属性,初始化之后如果给对象添加或移除属性,Vue无法检测到对象变化,从而视图不会更新.
2, 对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。
但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。
Vue.set(people,'name','王五');
或
this.$set(people,'name','王五');
3, 有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。
但是,这样添加到对象上的新 property 不会触发更新。
在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
对于数组来说:
Vue 不能检测以下数组的变动:
当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
解决方案:
// Vue.set(方式1)
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice(方式2)
vm.items.splice(indexOfItem, 1, newValue)
//以下方法会改变原数组
push() //接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度.
unshift() //在数组开头添加任意多个值,然后返回新的数组长度
shift() //用于删除数组的第一项,同时减少数组的length值,返回被删除的项
pop() //用于删除数组的最后一项,同时减少数组的length值,返回被删除的项
splice() //传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组.
sort(); //数组里的项从小到大排序(默认转换为字符串比较,如果需要按照数字大小排序,需要自己实现函数), 改变数组
reverse(); //用于颠倒数组中元素的顺序, 改变原数组
//以下方法都不影响原数组
slice(); //传入两个参数,分别是开始位置,要截取的长度,返回截取的新数组,不改变原数组
indexOf(); //要查找的元素在数组中的位置,如果没有则返回-1
includes(); //数组中是否包含某个元素
find(); //过滤 //返回数组中满足条件的第一个元素的值,如果没有,返回undefined
findIndex(); //返回数组中满足条件的第一个元素的索引(下标), 如果没有找到,返回-1
foreach(); //作用类似for循环, 数组中的每个元素执行一次提供的(回调)函数。这个方法没有返回值。不影响原数组
filter(); //遍历数组中所有的元素,返回值为符合条件的新数组,不改变原数组.(注意:不会对空数组进行检测)
map(); //遍历数组中每个元素,自定义处理后,返回值为每个处理后的元素组成的新数组, 如果某个元素没有return,则为null.不改变原数组(注意:不会对空数组进行检测)
some(); //数组中有至少一个元素满足就会返回true;所有元素都不满足返回值才会为false。
every(); //数组所有元素是否都符合指定条件,如果有一个元素不满足,则返回false
join(); //数组转字符串, 会改变原数组 //join(a),可以指定参数a,当做数组中元素的连接符
事件处理
- 传递方法名称
<div id="example-2">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">Greet</button>
</div>
- 除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:
<div id="example-3">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
- 有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) {
event.preventDefault()
}
alert(message)
}
}
事件修饰符
Demo
在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
.stop
.prevent
.capture
.self
.once
.passive
// 阻止单击事件继续传播
<a v-on:click.stop="doThis"></a>
// 提交事件不再重载页面 (指定submit时,点击按钮会重新加载页面,.prevent可以阻止页面重载)
<form v-on:submit.prevent="onSubmit"></form>
// 修饰符可以串联
<a v-on:click.stop.prevent="doThat"></a>
// 只有修饰符
<form v-on:submit.prevent></form>
// 添加事件监听器时使用事件捕获模式
// 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理
<div v-on:click.capture="doThis">...</div>
// 只当在 event.target 是当前元素自身时触发处理函数
// 即事件不是从内部元素触发的
<div v-on:click.self="doThat">...</div>
//2.1.4 新增
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
2.3.0 新增
Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符。
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
这个 .passive 修饰符尤其能够提升移动端的性能。
表单输入绑定
multiple的意思是,单选框展示一个变为展示多个选项,多选的方式为安装shift进行多选,展示多个
-
用 v-model 指令在表单 input、textarea 及 select 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
-
会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
-
对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input 事件。
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
text 和 textarea 元素使用 value property 和 input 事件;
checkbox 和 radio 使用 checked property 和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。
修饰符
.native
作用:在一个组件的根元素上直接监听一个原生事件
native表示原生事件,用于自定义组件, 将事件绑定到自定义组件的html标签上,dom.addEventListener('click', handler)
.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">
.sync
// 只需要在父组件绑定属性x上添加 .sync,在子组件内部就可以触发 update:属性名 来更新属性x
<child-sync :work.sync="student"></child-sync>
组件注册
组件名
(推荐:字母全小写且必须包含一个连字符)
全局注册
在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中.
Vue.component('my-component-name', { /* ... */ });
当直接在 DOM 中使用一个组件 (而不是在字符串模板或单文件组件) 的时候,我们强烈推荐遵循 W3C 规范中的自定义组件名 (字母全小写且必须包含一个连字符)。这会帮助你避免和当前以及未来的 HTML 元素相冲突。
组件名大小写,
定义组件名的方式有两种:
➤ 使用 kebab-case
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>。
➤ 使用 PascalCase
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name> 和 <MyComponentName> 都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
局部注册
在用到的文件中单独引入.
你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后在 components 选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
注意在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,
即这个变量名同时是:
用在模板中的自定义元素的名称
包含了这个组件选项的变量名
基础组件&自动化全局注册
可能你的许多组件只是包裹了一个输入框或按钮之类的元素,是相对通用的。我们有时候会把它们称为基础组件,它们会在各个组件中被频繁的用到
如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false.
注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。
Demo
Vue.component('my-component', {
inheritAttrs: false,
// ...
})
Prop
-
这意味着,不应该在一个子组件中改变prop, 如果改变了, 浏览器会在控制台中发出警告. - 一个非prop的attribute传给了子组件,这些attribute会被添加到这个组件的根元素上.
Prop 的大小写 (camelCase vs kebab-case)
HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
重申一次,如果你使用字符串模板,那么这个限制就不存在了。
传入一个数字时
即便 '42' 是静态的,我们仍然需要 'v-bind' 来告诉 Vue
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:likes="post.likes"></blog-post>
传入一个布尔值
<!-- 包含该 prop 没有值的情况在内,都意味着 `true`。-->
<blog-post is-published></blog-post>
<!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:is-published="false"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:is-published="post.isPublished"></blog-post>
传入一个数组
<!-- 即便数组是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:comment-ids="post.commentIds"></blog-post>
传入一个对象
<!-- 即便对象是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post
v-bind:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:author="post.author"></blog-post>
传入一个对象的所有 property
如果你想要将一个对象的所有 property 都作为 prop 传入,
你可以使用不带参数的 v-bind (取代 v-bind:prop-name)。
例如,对于一个给定的对象 post:
post: {
id: 1,
title: 'My Journey with Vue'
}
下面的模板:
<blog-post v-bind="post"></blog-post>
等价于:
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
子组件中想要改变prop,又不影响prop
注意: 在js中对象和数组是通过引用传入的(引用类型), 在子组件中改变这个对象或数组将会影响父组件的状态.
这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data property 并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
prop验证
Demo1
// 父组件给子组件传递任意类型数据
props: ['title','age','p'],
// 子组件限制父组件传递的数据类型
props: {
title: String,
age: {
type:[Number,String],
default:'99',
required:true
},
p: {
type: Object,
},
},
tip 注意: 注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
类型检查
type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认是否是一个类的实例
type 可以是下列原生构造函数中的一个:
tip 重点摘要:
String
Number
Boolean
Array
Object
Date
Function
Symbol
自定义事件
事件名
(推荐始终使用 kebab-case(短横线分隔) 的事件名。)
不同于组件和 prop,事件名不存在任何自动化的大小写转换。
// 如果使用 v-on:myEvent 将会自动转换为全小写 v-on:myevent
// 因为HTML是大小写不敏感的
<my-component v-on:my-event="doSomething"></my-component>
this.$emit('myEvent'); //只能监听到v-on:my-event
String 字符串用法
indexOf()
字符串中是否包含searchValue, 第二个参数可以忽略,表示从第几位开始检查.
str.indexOf(searchValue , fromIndex)
var str = 'bcdefabalkj';
console.log('返回结果:' + str.indexOf('a')); //返回值为第一次检索到该字符的位置为5
console.log('返回结果:' + str.indexOf('a',20)); //返回值为-1, 表示没有找到该字符
// 当被搜索的值为''或undefined时,返回值:
console.log('返回结果:' + str.indexOf('',11)); //0<fromIndex<=11时,返回值为fromIndex; fromIndex>11时,返回值都为11
console.log('返回结果:' + str.indexOf('',20)); //返回值为11, 表示str的长度
console.log('返回结果:' + str.indexOf(undefined,20)); //返回值为-1, 表示没有找到该字符
获取链接中最后一个&的参数
var str = "http://www.baidu.com?url=http://www.ncexc.com?token=token1&index=i&type=pdf";
var index = str.lastIndexOf("&");
str = str.substring(index + 1, str.length);
console.log(str); //type=pdf
split()
方法使用指定的分隔符字符串将一个String对象分割成子字符串数组
const str = 'The quick brown fox jumps over the lazy dog.';
const words = str.split(' ');
console.log(words[3]);
// expected output: "fox"
字符串中替换字符
str.replace(regexp|substr, newSubStr|function)
/*
使用正则表达式匹配字符串,可以替换所有的匹配结果.
在 replace() 中使用 global 和 ignore 选项
global:全局替换(g)
ignore:忽略大小写(i)
*/
var re = /apples/gi;
var str = "Apples are round, and apples are juicy. I like apples.";
var newstr = str.replace(re, "oranges");
console.log(newstr); //输出结果: oranges are round, and oranges are juicy. I like oranges.
/* 使用字符串替换字符串,只会替换第一个匹配结果,且区分大小写 */
var newstr2 = str.replace('apples', "oranges");
console.log(newstr2); //输出结果: Apples are round, and oranges are juicy. I like apples.
使用replace()交换两个单词的位置
var re = /(\w+)-(\w+)/; //表示匹配: 字母组合-字母组合
var str = "John-Smith";
/*
"$2, $1"是一个整体,作为第二个参数;
第一个参数re会被第二个参数替换掉;
第二个参数中$1表示a, $2表示b (原理可以理解: 字符串"a-b"会以特殊字符'-'拆分为2个参数$1,$2)
*/
var newstr = str.replace(re, "$2, $1"); //第二个参数可以任意指定格式
console.log(newstr); // Smith, John
全局自动注册自定义组件
(必须使用webpack的项目,vue-cli项目可以)
vuepress会自动注册components目录下所有的vue文件
全局自动注册自定义组件
//(globalComponents.js)
import Vue from 'vue'
function changeStr (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
//获取当前js同级的所有xxx.vue文件
const requireComponent = require.context('./', false, /\.vue$/)
// 查找同级目录下以vue结尾的组件
const install = () => {
//输出: "./HelloWorld.vue", "./VFor.vue", "./VTags.vue", "./Vhr.vue"
console.log(requireComponent.keys());
requireComponent.keys().forEach(fileName => {
let config = requireComponent(fileName)
console.log(config)
// 比如: ./VTags.vue 用正则替换./和.vue,拿到VTags
let componentName = changeStr(
fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')
)
Vue.component(componentName, config.default || config)
})
}
export default {
install // 对外暴露install方法
}
全局手动注册自定义组件
方式1: 在main.js中直接注册组件
方式2(推荐): 创建独立的js文件并注册组件,然后在main.js中全局引用组件
.prevent和.passive区别
tip 重点摘要:
- prevent 是拦截默认事件,passive是不拦截默认事件。
- passive和prevent冲突,不能同时绑定在一个监听器上。 参考地址>
详解
-
prevent: 某些标签拥有自身的默认事件,如a[href="#"],button[type="submit"] 这种标签在冒泡结束后会开始执行默认事件。注意默认事件虽然是冒泡后开始,但不会因为stop阻止事件传递而停止。
-
passive: 明明默认执行为什么会设置这样一个修饰符? 【浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。】
通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。
这里一般用在滚动监听,@scoll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度。
路由跳转
//A-B-C 从C-B返回时,B还能获取到query参数
this.$router.push({
path: "longcontract",
query: {
id: code
}
});
//下一页获取参数
this.$route.query.id;
//A-B-C 从C-B返回时,B不能获取到params参数
this.$router.push({
name: "longcontract",
params: {
id: code
}
});
this.$route.params.id;
Object.assign()
语法: Object.assign(target, ...sources)
参数:
target: 目标对象。
sources: 源对象。
返回值: 目标对象。
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
console.log(target); //{ a: 1, b: 2 }
const returnedTarget = Object.assign(target, source);
console.log(target); //改变了目标对象
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }
配置环境变量env
- 原理
采用`node.js`顶层对象中的`process.env`(进程环境,返回一个包含用户环境信息的对象)属性,
根据各个环境的配置文件区分和切换环境
只有以 `VUE_APP_` 开头的变量会被 `webpack.DefinePlugin` 静态嵌入到客户端的包中。
你可以在应用的代码中这样访问它们:
console.log(process.env.VUE_APP_SECRET)
`VUE_APP_*` 变量之外,在你的应用代码中始终可用的还有两个特殊的变量:
`NODE_ENV` - 会是 `"development"`、`"production"` 或 `"test"` 中的一个。
`BASE_URL` - 会和 `vue.config.js` 中的 `publicPath` 选项相符,即你的应用会部署到的基础路径。
提示:
你可以在 `vue.config.js` 文件中计算环境变量。它们仍然需要以 `VUE_APP_` 前缀开头。
process.env.VUE_APP_VERSION = require('./package.json').version
//在module.exports上面↑加
module.exports = {
// config
}
- 应用
1, 在项目根目录创建`.env.dev` 和`.env.prod`两个文件, 并填充环境变量信息
2, 在package.json中增加快捷指令
(如果不添加指令,会报TypeError: Cannot read property 'upgrade' of undefined)
3, 其他位置访问环境变量信息
console.log(process.env.NODE_ENV);
console.log(process.env.VUE_APP_TITLE);
console.log(process.env.VUE_APP_BASE_URL);