复习
-
组件注册
- 全局组件:用vue.component 必须有templete
- 全局注册的行为必须在根 Vue 实例 (通过
new Vue
) 创建之前发生 - 组件命名:
- 局部组件:定义组件名,给一个对象自变量。放的组件定义的option
-
options
- 关于选项、数据开头的
-
yarn init
在script写脚本
yarn start
-
局部组件可以自定义属性
-
props
-
prop定义规则:camelCase(驼峰命名) 需要使用其等价的kebab-case(短横线分隔命名法)
-
验证方式:手工定义props,不能约束属性类型
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 } } } })
-
属性类型[String,Number,Boolean,Array,Object,Function,Date,Symbol]
-
属性传递类型
- 静态传递
- 动态传递
-
继承方向:inhertAttrs
- true 允许继承
- false禁用继承(不会影响style和class的绑定)
-
-
单向数据流:不许在子组件直接修改props
- 解决方法:
- 解决方法:
-
sync修饰符
-
能不能在子组件修改父组件遍历
-
$parent 直接改
-
在子组件通过派发事件让父组件改变
-
bind绑定属性,加sync
-
通过update前缀的事件
-
带有
.sync
修饰符的v-bind
不能和表达式一起使用-
v-bind:title.sync=”doc.title + ‘!’” 是无效的
-
-
当我们用一个对象同时设置多个 prop 的时候,也可以将这个
.sync
修饰符和v-bind
配合使用:<text-document v-bind.sync="doc"></text-document>
-
-
自定义事件
-
需要始终使用 kebab-case 的事件名。
-
$emit
-
v-model 具有checkbox能力
-
将原始事件绑定到组件上,可以使用v-on 的.native修饰符
-
<base-input v-on:focus.native="onFocus"></base-input>
-
-
插槽slot
-
缩写 #( 该缩写只在其有参数的时候才可用)
-
在子组件通过slot读取内容
-
slot里没有内容,就自动读取默认值,
-
作用域
- 父级模板的所有内容都是在父组件定义的
-
作用域插槽
动态组件和异步组件
- 缓存操作 keep-alive
- activated 处理keep-alive缓存组件
- deactivated 离开keep-alive组件,没有卸载,
- activated,deactivated 钩子只针对keep-alive
处理边界情况 gap
-
在绝大多数情况下,我们最好不要触达另一个组件实例内部或手动操作 DOM 元素,不过也确实在一些情况下做这些事情是合适的。
-
访问根实例
- 所有的子组件都可以将这个实例作为一个全局 store 来访问或使用
- 获取根组件的数据
- 写入根组件的数据
- 访问根组件的计算属性
- 调用根组件的方法
-
访问父级组件实例
- 和
$root
类似,$parent
property 可以用来从一个子组件访问父组件的实例。它提供了一种机会,可以在后期随时触达父级组件,以替代将数据以 prop 的方式传入子组件的方式。
- 和
-
访问子组件实例或子元素
-
可以通过
ref
这个 attribute 为子组件赋予一个 ID 引用<base-input ref="usernameInput"></base-input> this.$refs.usernameInput
-
当
ref
和v-for
一起使用的时候,你得到的 ref 将会是一个包含了对应数据源的这些子组件的数组。 -
$refs
只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问$refs
。
-
-
依赖注入 inject
-
组件间数据传递(共享)
- 父子组价间:属性+props类型定义,$emit
- 亲兄弟组件间:中间人模式/状态提升
- 有共同祖先节点的组件:依赖注入
- BUS总线 (不推荐) :是vue的一个实例
- Vuex(通用的实现方案)
-
依赖注入:在某个祖先节点R上注入信息,R的后代都能拿到信息
-
提供器 provide provide:{x:0 }
- 修改了 provide,后代组件不响应
- 不要在后代组件试图修改 provide
-
注入器 inject
- inject:[‘x’] 把注入的内容用数组定义
-
bus总线
-
在当前模块内定义的变量,是不能再当前组件的实例上使用的
-
没有响应特性,需要有$forceUpDate()
-
递归组件 recursive
- 组件调用自己
- 可能会造成堆栈溢出,需要添加递归出口来终止循环
- 组件间循环引用
- 使用webpack异步组件可以解决
- 使用全局组件来解决
模板定义的替代品
- x-template
- 在一个
<script>
元素中,并为其带上text/x-template
的类型,然后通过一个 id 将模板引用过去 - x-template 需要定义在 Vue 所属的 DOM 元素外。
- 在一个
- 内联模板
- 内联模板需要定义在 Vue 所属的 DOM 元素内。
- 控制更新
- 强制更新forceUpdata
- v-once 创建低开销的静态组件
可复用性组合
混入 mixin
-
为什么要使用混入
- 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
-
全局混入
- Vue.mixin
- 一旦使用全局混入,它将影响每一个之后创建的 Vue 实例
-
局部混入
- mixin:[mixin]
-
会进行覆盖,组件内部定义的优先
-
mixin会深覆盖
- object.assign() 浅覆盖
-
生命周期钩子都会执行
-
生命周期钩子中,混入的先之后,自己的后执行
-
当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
-
值为对象的选项,例如
methods
、components
和directives
,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。var mixin = { methods: { foo: function () { console.log('foo') }, conflicting: function () { console.log('from mixin') } } } var vm = new Vue({ mixins: [mixin], methods: { bar: function () { console.log('bar') }, conflicting: function () { console.log('from self') } } }) vm.foo() // => "foo" vm.bar() // => "bar" vm.conflicting() // => "from self"
-
同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
var mixin = { created: function () { console.log('混入对象的钩子被调用') } } new Vue({ mixins: [mixin], created: function () { console.log('组件钩子被调用') } }) // => "混入对象的钩子被调用" // => "组件钩子被调用"
自定义指令 directive
-
需要写DOM操作
-
怎么定义
-
// 注册一个全局自定义指令 `v-focus` Vue.directive('focus',{ // 当被绑定的元素插入到 DOM 中时 inserted(el){ // 聚焦元素 el.focud() } })
-
-
如果想注册局部指令,组件中也接受一个
directives
的选项:directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } }
-
钩子函数
- bind : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted : 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
- updated: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。
- unbind:只调用一次,指令与元素解绑时调用。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
-
指令需要具备的要素
- v-开头
- 参数
- 修饰符
- 值
-
定义指令的范式
-
Vue.directive('font',(el,binding)=>{ el.style.color="red" }) //解构 Vue.directive('font',(el,{arg,modifiers,value})=>{ el.style.color=arg el.style.fontWeight=Object.keys(modifiers)[0] el.style.fontSize=value })
- el:指令所绑定的元素,可以用来直接操作 DOM。
- binding 是形参,是一个对象,可以用来直接操作DOM
- name:指令名,不包括
v-
前缀。 - value:指令的绑定值,例如:
v-my-directive="1 + 1"
中,绑定值为2
。 - oldvalue:指令绑定的前一个值,仅在
update
和componentUpdated
钩子中可用。无论值是否改变都可用。 - expression:字符串形式的指令表达式.例如
v-my-directive="1 + 1"
中,表达式为"1 + 1"
。 - arg:传给指令的参数,可选.例如
v-my-directive:foo
中,参数为"foo"
。 - modifiers:一个包含修饰符的对象。可以连缀.例如:
v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
- name:指令名,不包括
- vnode:Vue 编译生成的虚拟节点
- oldVnode:上一个虚拟节点,仅在
update
和componentUpdated
钩子中可用。 - 除了
el
之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的dataset
来进行。
-
-
如何取对象的key
- Object.keys
-
局部定义
渲染函数
-
特殊钩子函数render
-
Vue.component('Child',{ created(){ console.log('created') } render(createElement){ return createElement( 'div' , //创建的元素节点名字 { attrs:{ //自定义属性 aaa:'aaaaa' } }, //属性,可以写对象 'hello' //子节点 ) } mounted(){ console.log('mounted') } //render会自动调用,处于created和mouted之间 })
- 参数
- 名字
- 属性
- 子节点
- 参数
-
节点,树以及虚拟DOM
-
节点
- 每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样,每个节点都可以有孩子节点 (也就是说每个部分可以包含其它的一些部分)。
-
虚拟DOM
- Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM
-
createElement参数
-
(String|Object|Function)
- 一个 HTML 标签名、组件选项对象,或者resolve 了上述任何一种的一个 async 函数。必填项。
-
{Object}
- 一个与模板中 attribute 对应的数据对象。可选。
-
(String|Array)
- 子级虚拟节点 (VNodes),由
createElement()
构建而成,也可以使用字符串来生成“文本虚拟节点”。可选。
- 子级虚拟节点 (VNodes),由
-
-
语法糖 JSX
-
render(){ return <div>hello</div> }
-
-
约束
-
vNode必须唯一
-
如果你真的需要重复很多次的元素/组件,你可以使用工厂函数来实现
render: function (createElement) { return createElement('div', Array.apply(null, { length: 20 }).map(function () { return createElement('p', 'hi') }) ) }
-
插件 plugin
- 增加vue的全局功能或者property
- 在全局里加方法属性
- 添加全局资源:指令/过滤器/过渡等
- 通过全局混入来添加一些组件选项:如vue-route
- 添加实例方法,通过把他们添加到Vue.prototype上实现
- 一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如vue-route
开发插件
const myPlugin={}
//(function(){})(Vue)
myPlugin.install=function(Vue,options){
//1.全局的方法或者属性,自己定义的
Vue.foo=(args)=>{
}
Vue.set()
//2.添加全局的资源
Vue.component('my-component',{
template:`
<div>hello</div>`
})
Vue.directive('font',(el,binding)=>{
el.style.color=binding.value
})
//3.注入组件选项
Vue.mixin({
})
//4.添加实例的方法
Vue.protptype.$meta='aabbcc'
}
Vue.use(myPlugin,{ x:0})
-
1.添加全局的方法或者属性:在vue上直接调用
- Vue.component
-
2.添加全局的资源
- 内置组件
- component
- template
- keep-alive
- 内置组件
-
3.注入组件选项
-
4.添加实例的方法
使用插件
- 通过全局方法
Vue.use()
使用插件。它需要在你调用new Vue()
启动应用之前完成 Vue.use
会自动阻止多次注册相同插件,届时即使多次调用也只会注册一次该插件。
过滤器 filter
-
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和
v-bind
表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示<!-- 在双花括号中 --> {{ message | capitalize }} <!-- 在 `v-bind` 中 --> <div v-bind:id="rawId | formatId"></div>
-
你可以在一个组件的选项中定义本地的过滤器:
filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } }
-
或者在创建 Vue 实例之前全局定义过滤器
Vue.filter('capitalize', function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) }) new Vue({ // ... })
-
当全局过滤器和局部过滤器重名时,会采用局部过滤器:
-
过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数
-
过滤器可以串联:
{{ message | filterA | filterB }}
-
过滤器是 JavaScript 函数,因此可以接收参数:
{{ message | filterA('arg1', arg2) }}
’
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
- 或者在创建 Vue 实例之前全局定义过滤器
Vue.filter(‘capitalize’, function (value) {
if (!value) return ‘’
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// …
})
- 当全局过滤器和局部过滤器重名时,会采用局部过滤器:
- 过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数
- 过滤器可以串联:
{{ message | filterA | filterB }}
- 过滤器是 JavaScript 函数,因此可以接收参数:
{{ message | filterA(‘arg1’, arg2) }}
- 这里,`filterA` 被定义为接收三个参数的过滤器函数。其中 `message` 的值作为第一个参数,普通字符串 `'arg1'` 作为第二个参数,表达式 `arg2` 的值作为第三个参数。