Note 4
Vue登录后,无操作半小时后自动清除登录状态
在项目的页面入口文件
App.vue
文件中监听用户最后一次操作鼠标、键盘或滚动事件
import storage from 'store'
computed: {
token () {
return storage.get('TOKEN')
},
uid () {
return storage.get('UID')
},
userInfo () {
return storage.get('USER_INFO')
}
},
mounted () { // 使用防抖debounce,对于短时间内连续触发的事件(上面的滚动事件),防抖就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次
document.onmousemove = this.debounce(this.resetStatus, 3000)
document.onkeydown = this.debounce(this.resetStatus, 3000)
document.onscroll = this.debounce(this.resetStatus, 3000)
},
methods: {
debounce (fn, delay) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(fn, delay)
}
},
resetStatus () {
if (this.token) {
storage.set('TOKEN', this.token, new Date().getTime() + 30 * 60 * 1000)
storage.set('UID', this.uid, new Date().getTime() + 30 * 60 * 1000)
storage.set('USER_INFO', this.userInfo, new Date().getTime() + 30 * 60 * 1000)
}
}
}
Vue创建全局函数或变量
- 在
index.js
中创建getAction
函数,并全局使用
export function getAction (url, parameter) {
return request({
url: url,
method: 'get',
params: parameter
})
}
- 创建
globalUse.js
:
import { getAction } from './index'
// 方式一挂载到Vue.prototype:
import Vue from 'vue'
Vue.getAction = getAction // 使用时需先引入Vue,然后调用:Vue.getAction
Vue.prototype.$getAction = getAction // 使用:this.$getAction
// 方式二使用全局混入Vue.mixin:
Vue.mixin({ data () { return { getAction } } }) // 全局混入到data中,使用:this.getAction
// Vue.mixin({ methods: { getAction } }) // 全局混入到methods中,使用:this.getAction
- 在
main.js
中引入:
import Vue from 'vue'
import App from './App.vue'
import './utils/globalUse'
new Vue({
render: h => h(App)
}).$mount('#app')
Vue表单页监听浏览器回退
拦截并提示用户,点击确定执行返回,点击取消阻止返回
// 这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
beforeRouteLeave (to, from, next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
$router
新页面打开路由
onDetail (id) {
const routeUrl = this.$router.resolve({
path: '/show/detail',
query: { id }
})
window.open(routeUrl.href, '_blank')
}
npm link
没有参数的包文件夹中的
npm link
将在全局文件夹{prefix}/lib/node_modules/<package>
中创建一个符号链接,该符号链接链接到执行npm link
命令的包。它还将封装中的任何垃圾箱链接到 {prefix}/bin/{name}。 请注意,npm link 使用全局前缀(参见 npm prefix -g 的值)在某个其他位置,
npm link package-name
将创建一个从全局安装的package-name
到当前文件夹的node_modules/
的符号链接。
TIP
注意,package-name
取自 package.json
,而不是目录名称。
包名称可以选择以范围为前缀。 见 scope。 范围必须以 @ 符号开头,后跟斜杠
例如:
cd ~/projects/node-redis # go into the package directory
npm link # creates global link
cd ~/projects/node-bloggy # go into some other package directory.
npm link redis # link-install the package
现在,对 ~/projects/node-redis
的任何更改都将反映在 ~/projects/node-bloggy/node_modules/node-redis/
中。 请注意,链接应该指向包名称,而不是该包的目录名称。
你也可以将这两个步骤合二为一。 例如,以更短的方式执行上述用例:
cd ~/projects/node-bloggy # go into the dir of your main project
npm link ../node-redis # link the dir of your dependency
第二行相当于做:
(cd ../node-redis; npm link)
npm link redis
即它首先创建一个全局链接,然后将全局安装目标链接到你项目的 node_modules
文件夹中。
请注意,在这种情况下,你指的是目录名称 node-redis,而不是包名称 redis。
如果你的链接包有范围(参见 scope),你的链接命令必须包含该范围,例如
npm link @myorg/privatepackage
npm uninstall
npm uninstall [<@scope>/]<pkg>...
aliases: unlink, remove, rm, r, un
这将卸载一个包,完全删除代表它安装的所有 npm。
它还会从 package.json
中的 dependencies
、devDependencies
、optionalDependencies
和 peerDependencies
对象中删除包。
此外,如果你有 npm-shrinkwrap.json
或 package-lock.json
,npm
也会更新这些文件。
--no-save
会告诉 npm
不要从你的 package.json
、npm-shrinkwrap.json
或 package-lock.json
文件中删除包。
--save
或 -S
将告诉 npm
从你的 package.json
、npm-shrinkwrap.json
和 package-lock.json
文件中删除该包。 这是默认设置,但如果你的 npmrc
文件中有例如 save=false
,你可能需要使用它
在全局模式下(即,将 -g
或 --global
附加到命令中),它将当前包上下文作为全局包卸载。 在这种情况下,--no-save
被忽略。
范围是可选的,并遵循 scope
的通常规则。
监听键盘事件,绑定Enter按键
- 输入框监听键盘事件(
Enter
)
<a-input v-model="text" @keydown.enter="onClick" placeholder="请输入"/>
在当前页面监听键盘事件(
Enter
)onkeydown
:会在用户按下一个键盘按键时发生onkeypress
:会在键盘按键被按下并释放时发生。onkeyup
:会在键盘按键被松开时发生。 事件发生次序为:- onkeydown
- onkeypress
- onkeyup
在所有浏览器中
onkeypress
事件不是适用于所有按键(如: ALT, CTRL, SHIFT, ESC)。 监听一个用户是否按下按键请使用onkeydown
事件,所有浏览器都支持onkeydown
事件。js// 当前页面监听键盘确认键 // 等价于window.onkeydown = function (e) { … } window.addEventListener('keydown', (e) => { if (e.key === 'Enter') { // doing something } })
Vue2响应式原理
当你把一个普通的 JavaScript
对象传入 Vue
实例作为 data
选项,Vue
将遍历此对象所有的 property
,并使用 Object.defineProperty
把这些 property
全部转为 getter/setter
。Object.defineProperty
是 ES5
中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter
对用户来说是不可见的,但是在内部它们让 Vue
能够追踪依赖,在 property
被访问和修改时通知变更。
Vue中的template是如何渲染成页面的:
template
解析成抽象语法树Abstract Syntax Tree
;AST
编译成render
函数;render
函数构造成Virtual Dom
;Virtual Dom
转换成真实Dom
。
每个组件实例都对应一个 watcher
实例,它会在组件渲染的过程中把“接触”过的数据 property
记录为依赖。之后当依赖项的 setter
触发时,会通知 watcher
,从而使它关联的组件重新渲染。
Vue 无法检测 property 的添加或移除
由于 Vue
会在初始化实例时对 property
执行 getter/setter
转化,所以 property
必须在 data
对象上存在才能让 Vue
将它转换为响应式的。
对于已经创建的实例,Vue
不允许动态添加根级别的响应式 property
。但是,可以使用 Vue.set(object, propertyName, value)
方法向嵌套对象添加响应式 property
。
Vue 不能检测以下数组的变动
- 当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
声明响应式 property
由于 Vue 不允许动态添加根级响应式 property,所以你必须在初始化实例前声明所有根级响应式 property,哪怕只是一个空值
异步更新队列(vue.$nextTick())
Vue
在更新 DOM
时是异步执行的。只要侦听到数据变化,Vue
将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher
被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM
操作是非常重要的。然后,在下一个的事件循环“tick”
中,Vue
刷新队列并执行实际 (已去重的) 工作。Vue
在内部对异步队列尝试使用原生的 Promise.then
、MutationObserver
和 setImmediate
,如果执行环境不支持,则会采用 setTimeout(fn, 0)
代替。
例如,当你设置 vm.someData = 'new value'
,该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”
中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM
状态来做点什么,这就可能会有些棘手。虽然 Vue.js
通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM
,但是有时我们必须要这么做。为了在数据变化之后等待 Vue
完成更新 DOM
,可以在数据变化之后立即使用 Vue.nextTick(callback)
。这样回调函数将在 DOM
更新完成后被调用。
监听滚动事件
<script>
export default {
name: 'Scroll',
data () {
return {
// 可以在这里定义数据
}
},
mounted () {
window.addEventListener('scroll', this.handleScroll)
},
beforeDestroy () {
window.removeEventListener('scroll', this.handleScroll)
},
methods: {
handleScroll (event) {
// 处理滚动事件
console.log('The page has been scrolled')
// 你可以在这里访问 event 对象,比如 event.target.scrollTop
}
}
}
</script>