-
;当驼峰命名的首字母大写时,两种方法都能引用生效,都接受;
直接在DOM中使用时,只有kebab-case生效;
component
赋值变量,再组件components
内引用,实现复用。components
根目录中,通过import ComponentA from "./components/componentA"
引用。//入口文件中导入自动化全局组件配置
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
const requireComponent = require.context(
// 其组件目录的相对路径
'./components',
// 是否查询其子目录
false,
// 匹配基础组件文件名的正则表达式
/Base[A-Z]\w+\.(vue|js)$/
)
requireComponent.keys().forEach(fileName => {
// 获取组件配置
const componentConfig = requireComponent(fileName)
// 获取组件的 PascalCase 命名
const componentName = upperFirst(
camelCase(
// 剥去文件名开头的 `./` 和结尾的扩展名
fileName.replace(/^\.\/(.*)\.\w+$/, '$1')
)
)
// 全局注册组件
Vue.component(
componentName,
// 如果这个组件选项是通过 `export default` 导出的,
// 那么就会优先使用 `.default`,
// 否则回退到使用模块的根。
componentConfig.default || componentConfig
)
})
全局注册行为必须在根Vue实例创建之前。
HTML中特性名(属性)对大小写不敏感,不能直接在DOM中使用驼峰命名prop,但是在``template中不受限制。 建议使用kebab-case命名,避开这些问题。 书写格式:
props:[“key”]props:{key:类型}`
key:类型,指定值类型string\number\boolean\array\object
``v-bind:props=“val.title”`动态传值;
对象,数字,数组,布尔值等静态值,仍然需要
v-bind
绑定说明不是字符串,而是JS表达式:v-bind:props="42"
;
传入props下的一个对象时候,使用不带参数的v-bind=""
取代v-bind:prop-name=""
;
//javascript
props:{
post:{
id:1,
title:yo
}
}
//html
<blog-post v-bind="post"></blog-post>
//等价于
<blog-post :id="post.id" :title="post.title"></blog-post>
所有的prop都是父级单向下行绑定,但是对象或数组的props传入子组件函数,被改变时会影响父组件的状态。
props会在组件创建之前进行验证,因此实例的属性,如data、computed等在default或validator函数中,不可用.
参考:生命周期钩子
语法:
props:{
prop:Number,
prop:[Number,String],
prop:{
//string、number、boolean、array、object、date、function、symbol
type:String,
required:true
},
prop:{
type:Number,
default:100
},
prop:{
type:Object,
default:function(){
return {message:'hello'}
}
},
prop:{
validator:function(value){
//fn...return true or false
}
}
}
组件接受任意的特性,并被添加到根元素上,是因为:显性定义向一个子组件传入信息,而当不能考虑周全时,增加灵活性。
禁止特性的继承:组件选项中设置inheritAttrs:false
配合
$attrs
属性,手动继承属性:子组件内v-bind="$attrs"
手动继承父级属性。
事件名对大小写敏感,但是HTML对大小写不敏感,因此推荐始终使用kebab-case命名。
组件中的v-model
默认利用名为value
的prop
。和名为input
的event
,但是单选框和复选框会将value
用于不同目的,需手动component
中model
选项设置避免。
重新定义change事件和checked属性:
Vue.component("yo",{
model:{
prop:"checked",
event:"change"
},
props:{
checked:"checked"
},
template:`
`
})
怎么用?
一个组件的根元素上监听原生事件,v-on:event.native="fn"
或v-on="$listeners"
:
//javascript
//自定义input按钮
Vue.component('base-input', {
//取消子组件继承props
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// `Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `v-model` 的工作
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template: `
`
})
如此,自定义组件可以监听到所有的事件,包括原生事件和内部子元素事件
真正的双向绑定会带来维护上的问题:子组件可以修改父组件,且没有明显的改动来源。
因此,以updata:myPropName
的模式触发事件,实现。
子组件$emit
自定义事件updata:myPropName
,传参;父组件监听事件,更新
<text-doc
v-bind:propName="data.prop"
v-on:updata:propName="doc.prop=$event";>
</test-doc>
//简写
<text-doc v-bind:propName.sync="doc.prop">
带
.sync
的v-bind
不能使用JS表达式。无效。
不追踪数据变化
自定义模块可以插入slot,显示插入的任何东西,甚至是其他组件;
如:
;
但是slot的作用域在目前组件,不在模板;
可以在自定义模板的slot标签内预设默认显示;
具名插槽:
;
组件:
v-slot
只能用于template上;
子模板插槽prop上传,父组件v-slot:default="propName"
接收propName.user.data;
解构插槽prop:propName、{propName}、{propName:otherName}重命名、{propName = defaultValue}默认值
缩写:v-slot
=>#
;
动态插槽名:v-slot:[slotName]
;
实现子模板与父组件的通信与控制:插槽prop;
使用v-bind:is=""
切换不同组件,为了避免反复渲染,用
包裹组件,进行缓存。
<keep-alive>
<myComponent :is="currentComponent">myComponent>
keep-alive>
vue自带的工厂函数,按需加载组件:
Vue.component("componentName",function(resolve,reject){
//成功,回调函数
resolve({template:"..."})
//失败,返回错误
reject("error")
})
webpack写法:
Vue.component("componentName",function(resolve){
//Ajax请求,传入回调函数
require(["./my-component"],resolve)
})
webpack + ES5 :
// 全局注册,Vue全局
Vue.component("async-webpack-example",
()=>import('./my-component')
)
// 局部注册,vm某实例下
var vm = new Vue({
components:{
"my-component":()=>import("./my-component")
}
})
**处理加载状态**
```javascript
const AsyncComponent= ()=>({
//加载的组件
component:import('./Mycomponent.vue'),
//异步加载时
loading:loadingComponent,
//加载失败
error:errorComponent,
//加载延迟时间
delay:200,
//超时时限,否则返回加载失败
timeout:3000
})
访问元素和组件
$root
数据和方法;$parent
,替代[prop]传递的父子通信方式;ref
属性赋予子一个ID用以引用,父以this.$refs.refId
定位;当
ref
和v-for
一起时,会定位到子组件数组。
$refs
只在组件渲染之后生效,且不是响应式的,避免在component和computed属性中使用。
props
;//祖先组件注入
provide:function(){
return {
getMap:this.getMap
}
},
methods:{
getMap(){},
}
//后代组件依赖
inject:['getMap']
相关参考:Vuex
创建自定义事件$emit
,监听事件$on
一个事件,$once
一次事件,$off
停止监听。
例如:
$on(eventName,eventHandler)
,$emit , $on , $off并不是dispatchEvent,addEventListener,removeEventListener的别名
name
选项设置;name
值,所以可能到时无限循环,需要一个条件终止,例如v-if
。beforeCreate
时注册,或使用异步加载子组件;inline-template
特性typt="text/x-template"
属性,加上id后,实例引用id的模版;未被响应式系统追踪的状态,可以使用强制更新$forceUpdate
;
通常是某个地方处理错误,注意处理BUG;
template模版根元素加上v-once
属性,可以只计算一次并且缓存。
单元素、组件的过度(预装transition组件)
六种状态:
– .v-enter
进入过渡的开始状态,元素插入之前生效,下一帧移除
– .v-enter-active
生效时状态,插入之前生效,过度/动画完成移除,定义开始过渡过程时间、延迟、曲线函数(包含v-enter,v-enter-to)
– .v-enter-to
结束状态,元素插入下一帧生效,过度/动画完成移除
– .v-leave
离开过渡的开始状态
– .v-leave-active
生效时状态,定义离开过渡的时间、延迟、曲线函数(包含v-leave,v-leave-to)
– .v-leave-to
结束状态
当
没有命名时,默认
v-enter
,命名后name="my-transition"
,使用my-transition-enter
。
根据六种状态的类,进行CSS过渡效果;
和 过渡不同的是,在animationded
事件触发后删除。
VUE识别transitioned
或animationed
来监听过渡结束,一起时需要指明指针type="animationed/transitioned"
明确申明。
类似
的name
属性,定义类class,并使用第三方动画库结合VUE的过渡系统,达到效果:
enter-class
enter-active-class
enter-to-class
leave-class
leave-active-class
leave-to-class
或分别设置进入移除过渡时间
done()"
@after-enter=""
@enter-cancelled=""
@before-leave=""
@leave="()=>done()"
@after-leave=""
@leave-cancelled=""
// 延迟,1000或{enter:1000,leave:500}
:duration="1000"
>
<div v-if="isHide">
动画
div>
transiton>
添加v-bind:css="false"
,跳过css检测。
在enter和leave中必须使用done()函数进行回调,不然被同步调用,过渡立即完成。
初始渲染状态,同进入/离开的过渡一样,可以设置自定义类名属性,钩子事件
...
多个元素过渡,使用:key="keyValue"
标记来区分,触发效果
多个组件过渡,使用动态组件:is=""
即可
动画过渡特殊用法,以及状态过渡,有待开发。。。
全局
Vue.mixin({
data(){
return{
//...
}
},
create:function(){
//...
},
})
局部
var mixinName = {
//...
}
var vm = new Vue({
mixins:[mixinName],
})
全局
Vue.directive("focus",{
bind:function(el,binding,vnode,oldVnode){},
inserted:function(el){
el.focus()
},
update:function(){},
componentUpdated:function(){},
unbind:function(){},
})
局部
new Vue({
el:"#app",
directives:{
focus:{
inserted:function(el){
el.focus()
}
}
}
})
渲染函数 & JSX
new Vue({
render:function(){
//...
}
})
全局
Vue.filter("demo",fuction(value){
//...
return result
})
局部
new Vue({
filters:{
demo:function(value){
//...
return result
}
}
})
管道符“|”使用,可以传参数{{yo | filter("a","b")}}
,可以串联使用{{yo | filter1 | filter2}}
;