v-cloak
在渲染的时候,为了防止页面显示双大括号,可以使用v-cloak指令来隐藏未编译的(双大括号)标签直到实例准备完毕
使用是在css定义
[v-cloak] {
display: none;
}
<div v-cloak>
{{ message }}
</div>
数组的修改
vue不能检测以下变动的数组
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
举个例子:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
});
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
上面两个都不会重新渲染视图
为了解决第一类问题,以下两种方式都可以实现和vm.items[indexOfItem] = newValue
相同的效果,同时也将触发状态更新
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
为了解决第二类问题,你可以使用数组的splice
方法
vm.items.splice(newLength)
对象的修改
vue不能检测对象属性的添加或删除
var vm = new Vue({
data: {
a: 1
}
})
vm.a = 1; // vm.a是响应式的
vm.b = 2 // vm.b不是响应式的
如果要新增对象属性,可以用Vue.set(object, key, value)
Vue.set(vm.data, 'b', 2);
// 或者
vm.$set(vm.data, 'b', 2);
如果需要新增多个响应式属性,可以这样
vm.data = Object.assign({}, vm.data, {
c: 4,
d: 5
})
.sync修饰符
vue推荐通过事件触发的模式来同步父组件传递的属性值,例如
<Parent :title="title" @updateTitle="updateHandle"/>
父组件通过 :title
传递 title属性,设置监听 updateTitle
事件
注意子组件不允许直接修改 title 的值,如果在子组件 this.title 赋值的话会报错
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders
可以通过 this.$emit('updateTitle', Math.random())
来触发父组件做出修改 title 的操作
虽然通过上面可以实现父子间的通信,但是有一个更简单的方法就是使用 sync 修饰符来实现,在属性添加 .sync
修饰符后vue会自动帮我们绑定 :update:[prop]
事件方法,例如
<Parent :title.sync="title" />
相当于
<Parent :title="title" v-on:update:title="val => title = val" />
子组件就可以直接通过触发 :update:[prop]
方法提示父组件更新对应的title值
this.$emit('update:title', newTitle)
v-model的节流和防抖
有时候需要监听input框触发远程搜索功能,为了避免触发的频率过高,可以使用节流函数,第三方例如lodash或者underscore的_.throttle(function, wait, [options])
使用的方法如下,也可以使用防抖函数_.debounce(func, [wait=0], [options={}])
来实现输入完成后再触发
<template>
<div id="app">
<input type="text" v-model="uname">
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
uname: ''
}
},
watch: {
uname (val, oldVal) {
this.handleSearch(1, val);
}
},
methods: {
handleSearch: _.throttle(function(page, key) {
console.log(page, key);
}, 800)
}
}
</script>
按键修饰符
vue提供了常用按键的别名,方便我们使用
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
比如要实现按回车键提交表单,可以使用下面的方法
<!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 缩写语法 -->
<input @keyup.enter="submit">
vuex获取store的状态
获取store的state方法有两种
- 在组件里面通过 this.$store.state.count
this.$store.state.count
- 通过mapState辅助函数只是用来方便我们获取store里的状态
{
computed: mapState({
count: state => state.count
})
}
// 更简单的写法
{
computed: mapState(['count'])
}
如果要与组件自身的计算属性混合使用,可以使用对象展开运算符
computed: {
name () {
return this.firstName + this.lastName;
},
...mapState({
// ...
})
}
全局sass变量和mixin
本地安装 npm i sass-resources-loader -D
这个模块,在 build/utils.js
文件里面找到 cssLoaders
方法,添加如下代码
exports.cssLoaders = function (options) {
// ...
function resolveResouce(fileName) {
// 全局sass文件,可以直接在vue文件使用,全局的变量或者mixin
return path.resolve(__dirname, '../src/assets/scss/' + fileName)
}
function generateSassResourceLoader() {
var loaders = [
cssLoader,
'sass-loader', {
loader: 'sass-resources-loader',
options: {
resources: [
resolveResouce('_mixin.scss'),
resolveResouce('_variable.scss')
]
}
}
];
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// ...
}
最后 sass
和 scss
选项配置改为如下即可
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateSassResourceLoader(), // generateLoaders('sass', { indentedSyntax: true }),
scss: generateSassResourceLoader(), // generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
子组件继承父组件的样式
一般在写vue单文件组件样式的时候我们会写 scope 来限制样式的作用于当前组件,但是如果要让子组件也继承当前组件的样式,就可以通过深度作用选择器
.a >>> .b {
/* ... */
}
>>>
在sass/less文件的写法为/deep/
vue-router守卫
vue-router提供了三种守卫,全局守卫、路由独享守卫,组件内守卫
全局守卫有三个,beforeEach
和 beforeResolve
和 afterEach
router.beforeResolve 是2.5.0+新增的,在导航被确认之前,同时在所有的组件内守卫和异步路由组件被解析之后,解析守卫就会被调用
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
router.beforeResolve((to, from, next) => {
// ...
})
router.afterEach((to, from) => {
// ...
})
路由独享守卫只有一个,beforeEnter
在路由定义的时候单独配置的守卫
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
组件内守卫有三个 beforeRouteEnter
和 beforeRouteUpdate
和 beforeRouteLeav
这里需要注意两点
beforeRouteEnter
不能访问this
,因为守卫在导航确认前被调用,新的组件还没被创建,但是可以通过传一个回调给next
,就可以访问到实例了
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
beforeRouteLeave
是导航离开组件调用,可以通过next(false)
来取消跳转
一个完整的组件内路由导航守卫如下
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
vue-router解析流程图