8.函数式组件
无状态 无法实例化 内部没有任何生命周期函数 一切都是通过context参数传递
context 属性有: 1.props:提供所有 prop 的对象 2.children: VNode 子节点的数组 3.slots: 一个函数,返回了包含所有插槽的对象 4.scopedSlots: (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。 5.data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件 6.parent:对父组件的引用 7.listeners: (2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。 8.injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性
<template functional>
<div v-for="(item,index) in props.arr">{{item}}</div>
</template>
- components和Vue.component
局部注册
export default{
components:{home}
}
全局注册
Vue.component('home',home)
- Vue.extend
有时需要将一些元素挂载到元素上,需要用到extend
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{extendData}}</br>实例传入的数据为:{{propsExtend}}</p>',//template对应的标签最外层必须只有一个标签
data: function () {
return {
extendData: '这是extend扩展的数据',
}
},
props:['propsExtend']
})
// 创建的构造器可以挂载到元素上,也可以通过 components 或 Vue.component()注册使用
// 挂载到一个元素上。可以通过propsData传参.
new Profile({propsData:{propsExtend:'我是实例传入的数据'}}).$mount('#app-extend')
// 通过 components 或 Vue.component()注册
Vue.component('Profile',Profile)
11.mixins
有些组件有重复的js逻辑 校验 可以放入mixins
const mixin={
created(){
this.dealTime()
},
methods:{
dealTime(){
console.log('这是mixin的dealTime里面的方法');
}
}
}
export default{
mixins:[mixin]
}
- extends
只能单次扩展一个组件
const extend={
created(){
this.dealTime()
},
methods:{
dealTime(){
console.log('这是mixin的dealTime里面的方法');
}
}
}
export default{
extends:extend
}
- Vue.use()
会触发install函数
- install 第一个参数是vue的构造器,第二个参数是一个可选的选项对象
var MyPlugin = {}
MyPlugin.install = function (Vue,options) {
//添加全局资源
Vue.directive('click',{
bind(el,binding,vnode,oldVnode){
//绑定的准备工作,添加时间监听
console.log('指令my-directive的bind执行了');
},
inserted:function (el) {
//获取绑定的元素
console.log('指令my-directive的inserted执行啦')
},
update:function () {
//初始化会调用一次 更新也会调用
console.log('指令my-directive的update执行啦');
},
componentUpdated:function () {
console.log('指令my-directive的componentUpdated执行啦');
},
unbind:function () {
//做清理工作
// 例如一次bind时的事件监听器 console.log('指令my-directive的unbind执行啦');
}
})
//混入组件
Vue.mixin({
created:function () {
console.log('注入组件的created被调用啦');
console.log('options的值为',options)
}
})
Vue.prototype.$myMethod = function (methodOptions) {
console.log('实例方法myMethod被调用啦');
}
}
Vue.use(MyPlugin,{someOption:true})
- Vue.nextTick
页面加载后需要获取焦点 在dom更新完成结束后立即调用事件
mounted(){ //因为 mounted 阶段 dom 并未渲染完毕,所以需要$nextTick this.$nextTick(() => { this.$refs.inputs.focus() //通过 $refs 获取dom 并绑定 focus 方法 }) }
- Vue.directive
例如将color变成指令时可以使用
// 全局定义
Vue.directive("change-color",function(el,binding,vnode){
el.style["color"]= binding.value;
})
// 使用
<template>
<div v-change-color=“color”>{{message}}</div>
</template>
<script>
export default{
data(){
return{
color:'green'
}
}
}
</script>
1.bind 只调用一次,指令第一次绑定到元素时候调用,用这个钩子可以定义一个绑定时执行一次的初始化动作。 2.inserted:被绑定的元素插入父节点的时候调用(父节点存在即可调用,不必存在document中) 3.update: 被绑定与元素所在模板更新时调用,而且无论绑定值是否有变化,通过比较更新前后的绑定值,忽略不必要的模板更新 4.componentUpdate :被绑定的元素所在模板完成一次更新更新周期的时候调用 5.unbind: 只调用一次,指令月元素解绑的时候调用
17.Vue.filter
将时间戳转化成年月日的公共方法
// 使用
// 在双花括号中
{{ message | capitalize }}
// 在 `v-bind` 中
<div v-bind:id="rawId | formatId"></div>
// 全局注册
Vue.filter('stampToYYMMDD', (value) =>{
// 处理逻辑
})
// 局部注册
filters: {
stampToYYMMDD: (value)=> {
// 处理逻辑
}
}
// 多个过滤器全局注册
// /src/common/filters.js
let dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3')
export { dateServer }
// /src/main.js
import * as custom from './common/filters/custom'
Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))
- Vue.compile
在render模板中编译字符串 只在独立构建时有效
var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
data: {
msg: 'hello'
},
render: res.render,
staticRenderFns: res.staticRenderFns
})
- Vue.version
获取vue版本 做兼容
var version = Number(Vue.version.split('.')[0])
if (version === 2) {
// Vue v2.x.x
} else if (version === 1) {
// Vue v1.x.x
} else {
// Unsupported versions of Vue
}
20.Vue.set()
当你利用索引直接设置数组项时或者修改数组长度,由于Object.defineprototype()方法限制,数据不会响应式更新
// 利用 set
this.$set(arr,index,item)
// 利用数组 push(),splice()
21.Vue.config.keyCodes
自定义按键修饰别名
// 将键码为 113 定义为 f2
Vue.config.keyCodes.f2 = 113;
<input type="text" @keyup.f2="add"/>
22.Vue.config.performance
监听性能 只适用于开发模式和支持 performance.mark api的浏览器
23.Vue.config.errorHandler
1.场景:指定组件的渲染和观察期间未捕获错误的处理函数 2.规则: 从 2.2.0 起,这个钩子也会捕获组件生命周期钩子里的错误。同样的,当这个钩子是 undefined 时,被捕获的错误会通过 console.error 输出而避免应用崩溃 从 2.4.0 起,这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了 从 2.6.0 起,这个钩子也会捕获 v-on DOM 监听器内部抛出的错误。另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其 Promise 链的错误也会被处理 3.使用
Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
// 只在 2.2.0+ 可用
}
捕获全局异常
24.Vue.config.warnHandler
为Vue的运行时警告进行自定义处理 只在开发模式有效
Vue.config.warnHandler = function (msg, vm, trace) {
// `trace` 是组件的继承关系追踪
}
25.v-pre
不进行编译
<span v-pre>{{ this will not be compiled }}</span> 显示的是{{ this will not be compiled }}
<span v-pre>{{msg}}</span> 即使data里面定义了msg这里仍然是显示的{{msg}}
26.v-cloak
在网速慢的情况下 防止变量闪烁 在元素关联到示例后进行编译CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕
// template 中
<div class="#app" v-cloak>
<p>{{value.name}}</p>
</div>
// css 中
[v-cloak] {
display: none;
}
- v-once
有些 template中的静态dom没有改变,这时候只需要渲染一次,可以降低开销
`<span v-once> 这时只需要加载一次的标签</span>
`
28.事件修饰符
.stop阻止冒泡
.prevent 阻止默认行为
.self 仅绑定元素自身触发
.once 只触发一次
.passive 滚动事件的默认行为触发
29.按键修饰符和按键码
有的时候需要监听键盘的行为,如按下enter去查询接口等
// 对应键盘上的关键字
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
30.Vue-router
1.缓存和动画
<transition>
<keep-alive :include="['a', 'b']">
//或include="a,b" :include="/a|b/",a 和 b 表示组件的 name
//因为有些页面,如试试数据统计,要实时刷新,所以就不需要缓存
<router-view/> //路由标签
</keep-alive>
<router-view exclude="c"/>
// c 表示组件的 name值
</transition>
匹配先检查组件自身的name选项,如果name选项不可用,则匹配它的局部注册名称(父组件components 选项的键值),匿名组件不可用
2、全局路由钩子
router.beforeEach
router.beforeEach((to, from, next) => {
console.log('全局前置守卫:beforeEach -- next需要调用') //一般登录拦截用这个,也叫导航钩子守卫
if (path === '/login') {
next()
return
}
if (token) {
next();
}
})
router.beforeResolve
和 router.beforeEach 类似,区别是在导航被确认之前,并且在所有组件内守卫和异步路由组件被解析之后 在router.beforeEach 之后
router.afterEach
全局后置钩子 路由跳转结束之后被调用
3.组件路由钩子
beforeRouteEnter 在渲染该组件的对应路由前调用,next需要手动调用 可以给next一个vm来访问示例,在导航确认时执行
beforeRouteEnter (to, from, next) {
// 这里还无法访问到组件实例,this === undefined
next( vm => {
// 通过 `vm` 访问组件实例
})
}
beforeRouterUpdate 当前路由改变,并且该组件被复用时调用
beforeRouterLeave
4.路由模式
mode属性 hash或者history
5.Vue.$router
beforeRouteEnter (to, from, next) {
// 这里还无法访问到组件实例,this === undefined
next( vm => {
// 通过 `vm` 访问组件实例
})
}
6.Vue.$route
表示当前跳转的路由对象,属性有: name:路由名称 path:路径 query:传参接收值 params:传参接收值 fullPath:完成解析后的 URL,包含查询参数和 hash 的完整路径 matched:路由记录副本 redirectedFrom:如果存在重定向,即为重定向来源的路由的名字
this.$route.params.id:获取通过 params 或/:id传参的参数
this.$route.query.id:获取通过 query 传参的参数
- router-view 的key
由于vue恢复用相同的组件 将不再执行created,mounted钩子
`<router-view :key="$route.fullPath"></router-view>
`
31.Object.freeze
冻结属性
new Vue({
data: {
// vue不会对list里的object做getter、setter绑定
list: Object.freeze([
{ value: 1 },
{ value: 2 }
])
},
mounted () {
// 界面不会有响应,因为单个属性被冻结
this.list[0].value = 100;
// 下面两种做法,界面都会响应
this.list = [
{ value: 100 },
{ value: 200 }
];
this.list = Object.freeze([
{ value: 100 },
{ value: 200 }
]);
}
})
32.调试template
在开发环境挂载log
// main.js
Vue.prototype.$log = window.console.log;
// 组件内部
<div>{{$log(info)}}</div>
33.vue-loader 小技巧
preserveWhitespace 去掉空格
{
vue: {
preserveWhitespace: false
}
}
transformToRequire 自动配置
// vue-cli 2.x在vue-loader.conf.js 默认配置是
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
// 配置文件,如果是vue-cli2.x 在vue-loader.conf.js里面修改
avatar: ['default-src']
// vue-cli 3.x 在vue.config.js
// vue-cli 3.x 将transformToRequire属性换为了transformAssetUrls
module.exports = {
pages,
chainWebpack: config => {
config
.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.transformAssetUrls = {
avatar: 'img-src',
}
return options;
});
}
}
// page 代码可以简化为
<template>
<div>
<avatar img-src="./assets/default-avatar.png"></avatar>
</div>
</template>
34.为路径设置别名
// 在 webpack.base.config.js中的 resolve 配置项,在其 alias 中增加别名
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
vue3.0
// 在根目录下创建vue.config.js
var path = require('path')
function resolve (dir) {
console.log(__dirname)
return path.join(__dirname, dir)
}
module.exports = {
chainWebpack: config => {
config.resolve.alias
.set(key, value) // key,value自行定义,比如.set('@@', resolve('src/components'))
}
}
35.img加载失败
// page 代码
<img :src="imgUrl" @error="handleError" alt="">
<script>
export default{
data(){
return{
imgUrl:''
}
},
methods:{
handleError(e){
e.target.src=reqiure('图片路径') //当然如果项目配置了transformToRequire,参考上面 27.2
}
}
}
</script>
36。css
局部样式 scoped
deep 属性
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。