当前位置: 首页 > news >正文

有限公司破产债务怎么办优化方案教辅

有限公司破产债务怎么办,优化方案教辅,wordpress 页面下文章列表,怎样下载字体到wordpress目录 1.组件之处理边界情况 1.1 子组件访问根组件数据 1.2 子组件访问父组件数据 1.3 父组件访问子组件 1.4 依赖注入 1.5 程序化的事件侦听器 1.6 递归组件 1.7 内联模板 1.8 X-Template 1.9 强制更新 1.10 v-once 2.过渡效果与状态 2.1 过渡效果 2.1.1 单元素/…目录 1.组件之处理边界情况 1.1 子组件访问根组件数据 1.2 子组件访问父组件数据 1.3 父组件访问子组件 1.4 依赖注入 1.5 程序化的事件侦听器 1.6 递归组件 1.7 内联模板 1.8 X-Template 1.9 强制更新 1.10 v-once 2.过渡效果与状态 2.1 过渡效果 2.1.1 单元素/组件的过渡 2.1.1.1 过渡的CSS类名 2.1.1.2 CSS过渡 2.1.1.3 CSS动画 2.1.1.4 自定义过渡类名 2.1.1.5 同时使用过渡和动画 2.1.1.6 显性的过渡时间 2.1.1.7 JavaScript钩子 2.1.2 初始渲染的过渡 2.1.3 多个元素的过渡 2.1.3.1 过渡模式 2.1.4 多个组件的过渡 2.1.5 列表过渡 2.1.5.1 列表的进入/离开过渡 2.1.5.2 列表的排序过渡 2.1.5.3 列表的交错过渡 2.1.6 可复用的过渡 2.1.7 动态过渡 2.2 过渡状态 2.2.1 状态动画与侦听器 2.2.2 动态状态过渡 2.2.3 把过渡放到组件里 3.可复用性与组合 3.1 混入 3.1.1 基础 3.1.2 选项合并 3.1.2.1 数据对象合并 3.1.2.2 同名钩子函数合并 3.1.2.3 值为对象的选项合并 3.1.3 全局混入 3.1.4 自定义选项合并策略  3.2 自定义指令 3.2.1 简介 3.2.2 钩子函数 3.2.2.1 钩子函数参数 3.2.2.2 动态指令参数 3.2.3 函数简写 3.2.4 对象字面量 3.3 渲染函数与JSX 3.3.1 基础 3.3.2 节点、树以及虚拟DOM 3.3.3 createElement参数 3.3.3.1 深入数据对象 3.3.3.2 约束 3.3.4 使用JavaScript代替模板功能 3.3.4.1 v-if 和v-for 3.3.4.2 v-model 3.3.4.3 事件与按键修饰符 3.3.4.4 插槽 3.3.5 JSX 3.3.6 函数式组件 3.3.6.1 向子元素或子组件传递 attribute 和事件 3.3.6.2 slots() 和 children 对比  1.组件之处理边界情况 1.1 子组件访问根组件数据 在每个 new Vue 实例的子组件中其根实例可以通过 $root property 进行访问 代码实例 在根组件main.js中定义data数据methods及computed属性 页面子组件中调用根组件数据实现 templatedivh3子组件访问根组件数据/h3 left/left/div /template script //JavaScript 对象来定义局部组件 //left子组件 var LeftCom{data:function(){return {title:this.$root.appName //默认根组件数据appName}},methods:{//调用根组件方法getRootMethods(){this.$root.changeappName();this.titlethis.$root.appName;},//调用根组件计算属性getRootCompu(){let comvaluethis.$root.newTitle;this.titlecomvalue;},//写入根组件数据setRootData(){this.$root.appName你好,我的Vue2学习之旅;this.titlethis.$root.appName;}},template:divbutton clickgetRootMethods()调用根组件method/buttonbutton clickgetRootCompu()调用根组件computed/buttonbutton clicksetRootData()写入根组件data/button深入组件:{{title}}/div }; export default { //数据data(){return {countNum:1}},//注册局部组件components:{Left:LeftCom},//方法methods:{},//计算属性computed:{} } /script style scoped/style注意对于 demo 或非常小型的有少量组件的应用来说这是很方便的。不过这个模式扩展到中大型应用来说就不然了。因此在绝大多数情况下我们强烈推荐使用 Vuex 来管理应用的状态。 1.2 子组件访问父组件数据 使用 $parent property 可以用来从一个子组件访问父组件的实例。它提供了一种机会可以在后期随时触达父级组件以替代将数据以 prop 的方式传入子组件的方式。 var map this.$parent.map || this.$parent.$parent.map 在绝大多数情况下触达父级组件会使得你的应用更难调试和理解尤其是当你变更了父级组件的数据的时候。当我们稍后回看那个组件的时候很难找出那个变更是从哪里发起的。 此时我们建议使用依赖注入的方式  1.3 父组件访问子组件 尽管存在 prop 和事件有的时候你仍可能需要在 JavaScript 里直接访问一个子组件。为了达到这个目的你可以通过 ref 这个 attribute 为子组件赋予一个 ID 引用 templatedivh3父组件访问子组件/h3button clickchangeSubData通过父组件修改子组件data/button button clickgetSubMethod通过父组件调用子组件方法/button left refleftRef/left/div /template script //JavaScript 对象来定义局部组件 //left子组件 var LeftCom{data:function(){return {title:父组件访问子组件}},methods:{focusInput(){this.$refs.input.focus();}},template:div深入组件:{{title}}input refinput /div }; export default { //数据data(){return {countNum:1}},//注册局部组件components:{Left:LeftCom},//方法methods:{//通过父组件修改子组件datachangeSubData(){this.$refs.leftRef.title父组件访问子组件,设置子组件data;},getSubMethod(){this.$refs.leftRef.focusInput();}},//计算属性computed:{} } /script style scoped/style$refs 只会在组件渲染完成之后生效并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs  1.4 依赖注入 当我们从子组件访问父组件其中一层的父组件发生了改变的时候使用 $parent property 无法很好的扩展到更深层级的嵌套组件上这个时候就要用到依赖注入它用到了两个新的实例选项provide 和 inject provide 选项允许我们指定我们想要提供给后代组件的数据/方法该选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。 inject 选项来接收指定的我们想要添加在这个实例上的 property该选项应该是 一个字符串数组或   一个对象对象的 key 是本地的绑定名value 是       在可用的注入内容中搜索用的 key (字符串或 Symbol)或       一个对象该对象的          from property 是在可用的注入内容中搜索用的 key (字符串或 Symbol)          default property 是降级情况下使用的 value provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中 实例代码 templatedivh3组件的依赖注入/h3 leftleft-sub/left-sub/left/div /template script //JavaScript 对象来定义局部组件 //left子组件 var LeftCom{provide: function() {return {changeT:this.title}},data:function(){return {title:组件依赖注入}},template:div深入组件:{{title}}slot/slot/div }; var LeftSub{inject: [changeT],data:function(){return {parentTitle:}},created:function() {this.parentTitlethis.changeT;},template:div父组件标题{{parentTitle}}/div }; export default { //数据data(){return {}},//注册局部组件components:{Left:LeftCom,LeftSub:LeftSub},//方法methods:{},//计算属性computed:{} } /script style scoped/style1.5 程序化的事件侦听器 在前面的学习中我们知道$emit 的用法它可以被 v-on 侦听但是 Vue 实例同时在其事件接口中提供了其它的方法 通过 $on(eventName, eventHandler) 侦听一个事件通过 $once(eventName, eventHandler) 一次性侦听一个事件通过 $off(eventName, eventHandler) 停止侦听一个事件 当你需要在一个组件实例上手动侦听事件时它们是派得上用场的。它们也可以用于代码组织工具。 $on、$once、$off实例代码 templatedivh3$on侦听事件/h3 button clickaddNum$on侦听加法事件/button button clickreduceNum$once侦听减法事件/button button clickoffAdd$off停止侦听加法事件/buttoninput v-modelnumVal /pthis.$on(add, eventHandler) 定义一个监听的add事件并指定他的执行对象/执行函数eventHandler/ppthis.$emit(add, my params)消费add事件/pp使用on和emit后我们可以把事件的定义和消费实现逻辑的解耦可以在父组件监听($on)子组件中直接调用事件($emit)/pp要强调的一点是$on和$emit事件必须是在一个公共的实例上才能触发/p /div /template script export default { //数据data(){return {numVal:1}},//注册局部组件components:{},//方法methods:{addNum(){//消费add事件this.$emit(add);},reduceNum(){this.$emit(reduce);},offAdd(){this.$off(add);}},//计算属性computed:{},//渲染dommounted:function(){ //定义一个监听的add事件并指定他的执行对象/执行函数 this.$on(add,function(){console.log(触发方法add);this.numVal;});//$once监听事件只执行一次this.$once(reduce,function(){console.log(触发方法reduce);this.numVal--;});} } /script style scoped/style1.6 递归组件 组件是可以在它们自己的模板中调用自身的。不过它们只能通过 name 选项来做这件事 name: unique-name-of-my-component 当你使用 Vue.component 全局注册一个组件时这个全局的 ID 会自动设置为该组件的 name 选项。  Vue.component(unique-name-of-my-component, {   // ... }) 稍有不慎递归组件就可能导致无限循环  name: stack-overflow, template: divstack-overflow/stack-overflow/div 类似上述的组件将会导致“max stack size exceeded”错误所以请确保递归调用是条件性的 (例如使用一个最终会得到 false 的 v-if)。 递归组件基础实例代码 templatedivh3递归组件基础使用/h3 left :myTitledefaultTitle/left/div /template script //JavaScript 对象来定义局部组件 //left子组件 var LeftCom{name:left,props:[myTitle],data:function(){return {title:递归,show:false}},methods:{componentsSelf(){this.showtrue;}},template:div深入组件:{{myTitle}}button clickcomponentsSelf组件自调用/buttonleft v-ifshow :myTitletitle/left/div }; export default { //数据data(){return {titleArrary:[1,2,3],defaultTitle:hello vue}},//注册局部组件components:{Left:LeftCom},//方法methods:{},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/style1.7 内联模板 当 inline-template 这个特殊的 attribute 出现在一个子组件上时这个组件将会使用其里面的内容作为模板而不是将其作为被分发的内容。这使得模板的撰写工作更加灵活。 内联模板实例代码 templatedivh3内联模板/h3 left :myTitledefaultTitle inline-templatedivphello world/p/div/left/div /template script //JavaScript 对象来定义局部组件 //left子组件 var LeftCom{props:[myTitle],data:function(){return {title:递归}},methods:{},template:div深入组件:{{myTitle}}/div }; export default { //数据data(){return {defaultTitle:内联模板}},//注册局部组件components:{Left:LeftCom},//方法methods:{},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/style内联模板会把子组件中的内容替换为内联模板的内容比如上述实例的最终渲染结果为 1.8 X-Template X-Template是在 JavaScript 标签里使用 text/x-template 类型并且指定一个id来定义模板的一种方式例如 script typetext/x-template idhello-world-template pHello hello hello/p /script Vue.component(hello-world, { template: #hello-world-template })  x-template 需要定义在 Vue 所属的 DOM 元素外。 这些可以用于模板特别大的 demo 或极小型的应用但是其它情况下请避免使用因为这会将模板和该组件的其它定义分离开。  1.9 强制更新 在vue的开发过程中数据的绑定通常来说都不用我们操心例如在​​data​​中有一个​​msg​​的变量只要修改它那么在页面上​​msg​​的内容就会自动发生变化。但是如果对于一个复杂的对象例如一个对象数组直接去给数组上某一个元素增加属性或者直接把数组的​​length​​变成0vue可能就无法知道发生了改变。这个其实就是考验对于双向绑定的更进一步的理解应用了。 在Vue中双向绑定属于自动档然而在特定的情况下需要手动触发“刷新”操作目前有四种方案可以选择 刷新整个页面使用v-if标记使用内置的forceUpdate方法使用key-changing优化组件 使用forceUpdate是比较好的一种方式比如说我们尝试直接给某个​​object​​增加一个属性发现页面上没有效果直接将length变成0来清空数组也没有效果 关键代码如下 change: function(index) { // 增加性格属性 this.girls[idx].character lovely; }, clear: function() { // 清空数组 this.girls.length 0; } 按照上面的写法没有产生想要的效果是因为没有按照vue的规范去写因为文档里面写了对于深层的最好用$set方法这样vue就可以知道发生了变化同时vue也不建议直接修改length而是给一个空数组来置空。 如果我们按照vue的规范去写的是可以实现变化的 change: function(index) { // 增加性格属性 this.$set(this.girls[idx],character,lovely) }, clear: function() { // 清空数组 this.girls []; } 如果我们不想利用​​$set​​去设置非要按照我们第一种方式去写可以实现么可以的就是利用​​$forceUpdate​​此时修改了数据然而页面层没有变动之后通过日志打印的方式确认数据是否有修改过之后再确认有没有监听到用​​$forceUpdate​​就相当于按照最新数据给渲染一下。  change: function(index) { this.girls[idx].character 男; this.$forceUpdate(); }, clear: function() { this.girls.length 0; this.$forceUpdate(); } 这种做法实际上并不推荐官方说如果你现在的场景需要用​​forceUpdate​​方法 ,那么99%是你的操作有问题如上data里不显示声明对象的属性之后添加属性时正确的做法时用 ​​$set()​​方法所以​​forceUpdate​​请慎用。 该同等效果的window.location.reload()  1.10 v-once 只渲染元素和组件一次随后的渲染使用了此指令的元素/组件及其所有的子节点都会当作静态内容并跳过这可以用于优化更新性能。 常见用法实例代码 templatedivh3v-once/h3 button clickchangeMsg修改消息/buttoninput v-once v-modelmsg/p{{msg}}/p/div /template script export default { //数据data(){return {msg:hello world,countNum:1}},//注册局部组件components:{},//方法methods:{changeMsg(){this.msg你好消息this.countNum;this.countNum;}},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/style当msg值改变时input文本框中的内容不会变化而p元素的值会随之变化  2.过渡效果与状态 2.1 过渡效果 Vue 在插入、更新或者移除 DOM 时提供多种不同方式的应用过渡效果。包括以下工具 在 CSS 过渡和动画中自动应用 class可以配合使用第三方 CSS 动画库如 Animate.css在过渡钩子函数中使用 JavaScript 直接操作 DOM可以配合使用第三方 JavaScript 动画库如 Velocity.js 2.1.1 单元素/组件的过渡 Vue 提供了 transition 的封装组件在下列情形中可以给任何元素和组件添加进入/离开过渡 条件渲染 (使用 v-if)条件展示 (使用 v-show)动态组件组件根节点 元素封装成过渡组件之后在遇到插入或删除时Vue 将 自动嗅探目标元素是否有 CSS 过渡或动画并在合适时添加/删除 CSS 类名。如果过渡组件设置了过渡的 JavaScript 钩子函数会在相应的阶段调用钩子函数。如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画DOM 操作插入/删除在下一帧中立即执行。(注意此指浏览器逐帧动画机制与 Vue和Vue的 nextTick 概念不同 2.1.1.1 过渡的CSS类名 在进入/离开的过渡中会有 6 个 class 切换。 v-enter定义进入过渡的开始状态。在元素被插入之前生效在元素被插入之后的下一帧移除。v-enter-active定义进入过渡生效时的状态。在整个进入过渡的阶段中应用在元素被插入之前生效在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间延迟和曲线函数。v-enter-to2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除)在过渡/动画完成之后移除。v-leave定义离开过渡的开始状态。在离开过渡被触发时立刻生效下一帧被移除。v-leave-active定义离开过渡生效时的状态。在整个离开过渡的阶段中应用在离开过渡被触发时立刻生效在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间延迟和曲线函数。v-leave-to2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除)在过渡/动画完成之后移除。) 对于这些在过渡中切换的类名来说如果你使用一个没有名字的 transition则 v- 是这些类名的默认前缀。如果你使用了 transition namemy-transition那么 v-enter 会替换为 my-transition-enter。 v-enter-active 和 v-leave-active 可以控制进入/离开过渡的不同的缓和曲线  2.1.1.2 CSS过渡 实例代码 templatedivh3CSS过渡/h3 button clickshow!show切换渲染/buttontransition nameslide-fadep v-ifshowHello World/p/transition /div /template script export default { //数据data(){return {show:true}},//注册局部组件components:{},//方法methods:{},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/* 可以设置不同的进入和离开动画 *//* 设置持续时间和动画函数 */.slide-fade-enter-active {transition: all .3s ease;}.slide-fade-leave-active {transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);}.slide-fade-enter, .slide-fade-leave-to/* .slide-fade-leave-active for below version 2.1.8 */ {transform: translateX(10px);opacity: 0;} /style2.1.1.3 CSS动画 CSS 动画用法同 CSS 过渡区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除而是在 animationend 事件触发时删除 实例代码 templatedivh3CSS动画/h3 button clickshow!show切换渲染/buttontransition namebouncep v-ifshowHello World/p/transition /div /template script export default { //数据data(){return {show:true}},//注册局部组件components:{},//方法methods:{},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped.bounce-enter-active {animation: bounce-in .5s;}.bounce-leave-active {animation: bounce-in .5s reverse;}keyframes bounce-in {0% {transform: scale(0);}50% {transform: scale(1.5);}100% {transform: scale(1);}} /style2.1.1.4 自定义过渡类名 我们可以通过以下属性来自定义过渡类名 enter-classenter-active-classenter-to-class (2.1.8)leave-classleave-active-classleave-to-class (2.1.8) 他们的优先级高于普通的类名这对于 Vue 的过渡系统和其他第三方 CSS 动画库如 Animate.css 结合使用十分有用。 实例代码 templatedivh3自定义过渡的类名/h3 button clickshow!show切换渲染/buttontransition enter-active-classanimate__animated animate__tada leave-active-classanimate__animated animate__bounceOutRightp v-ifshowHello World/p/transition /div /template script export default { //数据data(){return {show:true}},//注册局部组件components:{},//方法methods:{},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/styleanimate的引用说明 1、npm i animate.css--save 安装 2、main.js中全局引入 import animate from animate.css Vue.use(animate) 3、animate css样式引入注意需要添加前缀animate__ transition  enter-active-classanimate__animated animate__tada leave-active-classanimate__animated animate__bounceOutRight         p v-ifshowHello World/p       /transition   2.1.1.5 同时使用过渡和动画 Vue 为了知道过渡的完成必须设置相应的事件监听器。它可以是 transitionend 或 animationend这取决于给元素应用的 CSS 规则。如果你使用其中任何一种Vue 能自动识别类型并设置监听。 但是在一些场景中你需要给同一个元素同时设置两种过渡动效比如 animation 很快的被触发并完成了而 transition 效果还没结束。在这种情况中你就需要使用 type attribute 并设置 animation 或 transition 来明确声明你需要 Vue 监听的类型。 实例代码 templatedivh3同时使用过渡和动画/h3 button clickshow!show切换渲染/buttontransition namefade enter-active-classanimate__animated animate__tada fade-enter-active leave-active-classanimate__animated animate__bounceOutRight fade-leave-activep v-ifshowHello World/p/transition /div /template script export default { //数据data(){return {show:true}},//注册局部组件components:{},//方法methods:{},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped /*延迟加载*/.fade-enter, .fade-leave-to{opacity: 0;}.fade-enter-active, .fade-leave-active{transition: opacity 5s;} /style2.1.1.6 显性的过渡时间 在很多情况下Vue 可以自动得出过渡效果的完成时机。默认情况下Vue 会等待其在过渡效果的根元素的第一个 transitionend 或 animationend 事件。然而也可以不这样设定——比如我们可以拥有一个精心编排的一系列过渡效果其中一些嵌套的内部元素相比于过渡效果的根元素有延迟的或更长的过渡效果。 在这种情况下你可以用 transition 组件上的 duration prop 定制一个显性的过渡持续时间 (以毫秒计) transition :duration1000.../transition 你也可以定制进入和移出的持续时间 transition :duration{ enter: 500, leave: 800 }.../transition  2.1.1.7 JavaScript钩子 可以在属性中声明 JavaScript 钩子包含 before-enterenterafter-enterbefore-leaveleaveafter-leave 实例代码 templatedivh3JavaScript钩子/h3 button clickshow!show切换渲染/buttontransition enter-active-classanimate__animated animate__tada leave-active-classanimate__animated animate__bounceOutRightv-on:before-enterbeforeEnterv-on:enterenterv-on:after-enterafterEnterv-on:beofre-leavebeforeLeavev-on:leaveleavev-on:after-leaveafterLeavep v-ifshowHello World/p/transition /div /template script import Velocity from velocity-animate; export default { //数据data(){return {show:true}},//注册局部组件components:{},//方法methods:{//进入前触发事件beforeEnter:function(el){console.log(进入前触发事件);el.style.opacity 0;el.style.transformOrigin left; },//进入时触发事件enter:function(el,done){console.log(进入时触发事件);Velocity(el, { opacity: 1, fontSize: 5em }, { duration: 300 });Velocity(el, { fontSize: 1em }, { complete: done });},//进入后触发事件afterEnter:function(el){console.log(进入后触发事件);el.style.fontSize30px;},//离开前触发事件beforeLeave(el){console.log(离开前触发事件);el.style.opacity 0;el.style.transformOrigin right; },//离开时触发事件leave(el,done){console.log(离开时触发事件);Velocity(el, { opacity: 1, fontSize: 5em }, { duration: 300 });Velocity(el, { fontSize: 1em }, { complete: done });},//来开后触发事件afterLeave(el){console.log(离开时触发事件);el.style.fontSize30px;}},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/style关于Velocity插件 Velocity是一个简单易用高性能且功能丰富的轻量级JavaScript动画库它拥有颜色动画转换动画transforms、循环、缓动、SVG动画、和滚动动画等特色功能 支持Chaining链式动画当一个元素连续应用多个velocity()时动画以队列的方式执行  1、执行npm install velocity-animate命令进行安装 2、页面引入 import  Velocity from velocity-animate;  2.1.2 初始渲染的过渡 通过 appear 属性设置节点在初始渲染的过渡 appear与进入/离开过渡一样可以自定义过渡CSS列名可以设置JavaScript钩子 自定义过渡类名的属性 appear-classappear-active-classappear-to-class (2.1.8) JavaScript钩子 before-appearappearafter-appearappear-cancelled appear-cancelled的触发条件就是before-appear/appear两个钩子函数中有不显示该节点的操作v-if/ v-show都会触发appear-cancelled钩子函数。实际场景不多一般在动画执行过程中被用户取消后可以执行一些操作。  实例代码 templatedivh3初始渲染的过渡/h3 button clickshow!show切换渲染/buttontransition appearappear-active-classanimate__animated animate__tada appear-to-classanimate__animated animate__fadeInv-on:before-appearbeforeAppearv-on:appearappearv-on:after-appearafterAppearv-on:appear-cancelledappearCancelledp v-ifshowHello World/p/transition /div /template script import Velocity from velocity-animate; export default { //数据data(){return {show:true}},//注册局部组件components:{},//方法methods:{//初始渲染前触发事件beforeAppear:function(el){console.log(初始渲染前触发事件);el.style.opacity 0;el.style.transformOrigin left;//this.showfalse;//此代码可触发appear-cancelled事件 },//初始渲染时触发事件appear:function(el,done){console.log(初始渲染时触发事件);Velocity(el, { opacity: 1, fontSize: 5em }, { duration: 300 });Velocity(el, { fontSize: 1em }, { complete: done });},//初始渲染后触发事件afterAppear:function(el){console.log(初始渲染后触发事件);el.style.fontSize30px;},//初始渲染取消触发事件appearCancelled(el){console.log(初始渲染取消触发事件);el.style.opacity 0;el.style.transformOrigin right; }},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/style2.1.3 多个元素的过渡 我们平时在多个不同元素上会使用v-if/v-show来控制元素是否显示这也是控制多个元素过渡的一种方式但是这样使用时需要注意 当有相同标签名的元素切换时需要通过 key attribute 设置唯一的值来标记以让 Vue 区分它们否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要给在transition组件中的多个元素设置 key 是一个更好的实践。 实例代码 templatedivh3多个元素的过渡/h3 button clickchangeBtn变换按钮/buttontransitionbutton v-bind:keybuttonState{{buttonText}}/button/transition /div /template script export default { //数据data(){return {buttonState:save}},//注册局部组件components:{},//方法methods:{ changeBtn(){if(this.buttonStatesave){this.buttonStateedit;}else if(this.buttonStateedit){this.buttonStatedelete;}else if(this.buttonStatedelete){this.buttonStatesave;}} },//计算属性computed:{buttonText:function (){let returnVal保存;if(this.buttonStatesave){returnVal保存;}else if(this.buttonStateedit){returnVal编辑;}else if(this.buttonStatedelete){returnVal删除;}return returnVal;}},//渲染dommounted:function(){ } } /script style scoped/style2.1.3.1 过渡模式 在上面的实例中我们会发现当我们改变buttonState值的时候会发现两个按钮每次都会刷新一个离开过渡的时候另一个开始进入过渡这是 transition 的默认行为 - 进入和离开同时发生。 同时生效的进入和离开的过渡不能满足所有要求所以 Vue 提供了过渡模式 in-out新元素先进行过渡完成之后当前元素过渡离开out-in当前元素先进行过渡完成之后新元素过渡进入 我们在transition中设置mode属性为out-in就可已解决这个问题 transition modeout-in     !-- ... the buttons ... --  /transition     2.1.4 多个组件的过渡 多个组件的过渡我们不需要使用key属性只需要使用动态组件 实例代码 templatedivh3多个组件的过渡/h3 button clickchangeCom变换组件/buttontransition modeout-incomponent :iscomState/component/transition /div /template script //left子组件 var LeftCom{data:function(){return {title:多个组件的过渡}},methods:{},template:divLeft深入组件:{{title}}/div }; //right组件 var RightCom{data:function(){return {title:多个组件的过渡}},methods:{},template:divRight组件/div }; export default { //数据data(){return {comState:Left}},//注册局部组件components:{Left:LeftCom,Right:RightCom},//方法methods:{ changeCom(){if(this.comStateLeft){this.comStateRight;}else if(this.comStateRight){this.comStateLeft;}} },//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped/style2.1.5 列表过渡 列表过渡我们需要用到transition-group组件其特点 不同于 transition它会以一个真实元素呈现默认为一个 span。你也可以通过 tag 属性 更换为其他元素。过渡模式不可用因为我们不再相互切换特有的元素。内部元素总是需要提供唯一的 key attribute 值。CSS 过渡的类将会应用在内部的元素中而不是这个组/容器本身。 2.1.5.1 列表的进入/离开过渡 实例代码 templatedivh3列表的进入/离开过渡/h3 button clickadd添加列表元素/buttonbutton clickremove删除列表元素/buttontransition-group namelist tagpspan v-foritem in items v-bind:keyitem classlist-item{{item}}/span/transition-group /div /template script export default { //数据data(){return {items: [1,2,3,4,5,6,7,8,9],nextNum: 10}},//注册局部组件components:{},//方法methods:{ randomIndex: function () {return Math.floor(Math.random() * this.items.length)},//添加列表元素方法add: function () {this.items.splice(this.randomIndex(), 0, this.nextNum)},//删除列表元素方法remove: function () {this.items.splice(this.randomIndex(), 1)},},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped .list-item {display: inline-block;margin-right: 10px; } .list-enter-active, .list-leave-active {transition: all 1s; } .list-enter, .list-leave-to /* .list-leave-active for below version 2.1.8 */ {opacity: 0;transform: translateY(30px); } /style2.1.5.2 列表的排序过渡 在列表的进入/离开实例中代码运行时当添加和移除元素的时候周围的元素会瞬间移动到他们的新布局的位置而不是平滑的过渡这时我们需要用到排序过渡 要实现排序过渡我们这里需要使用lodash插件 1、执行 npm i lodash --save 命令安装插件 2、页面中引入lodash, import Lodash from lodash; 实例代码 templatedivh3列表的排序过渡/h3 button clickadd添加列表元素/buttonbutton clickremove删除列表元素/buttonbutton clickreorder随机排序/buttontransition-group namelist tagpspan v-foritem in items v-bind:keyitem classlist-item{{item}}/span/transition-group /div /template script import Lodash from lodash; export default { //数据data(){return {items: [1,2,3,4,5,6,7,8,9],nextNum: 10}},//注册局部组件components:{},//方法methods:{ randomIndex: function () {return Math.floor(Math.random() * this.items.length);},//添加列表元素方法add: function () {this.items.splice(this.randomIndex(), 0, this.nextNum);},//删除列表元素方法remove: function () {this.items.splice(this.randomIndex(), 1);},//元素排序过渡reorder: function () {this.items Lodash.shuffle(this.items);}},//计算属性computed:{},//渲染dommounted:function(){ } } /script style scoped .list-item {display: inline-block;margin-right: 10px; } .list-enter-active, .list-leave-active {transition: all 1s; } .list-enter, .list-leave-to /* .list-leave-active for below version 2.1.8 */ {opacity: 0;transform: translateY(30px); } /style排序过渡的实现是Vue 使用了一个叫 FLIP 简单的动画队列使用 transforms 将元素从之前的位置平滑过渡新的位置  需要注意的是使用 FLIP 过渡的元素不能设置为 display: inline 。作为替代方案可以设置为 display: inline-block 或者放置于 flex 中 FLIP 动画不仅可以实现单列过渡多维网格也同样可以过渡 2.1.5.3 列表的交错过渡 通过 data 属性 与 JavaScript 通信就可以实现列表的交错过渡 实例代码 templatedivh3列表的交错过渡/h3 input v-modelquerytransition-group namestaggered-fade tagulv-bind:cssfalsev-on:before-enterbeforeEnterv-on:enterenterv-on:leaveleaveli v-for(item, index) in computedList v-bind:keyitem.msg v-bind:data-indexindex{{ item.msg }}/li/transition-group /div /template script import Velocity from velocity-animate; export default { //数据data(){return {query: ,list: [{ msg: Bruce Lee },{ msg: Jackie Chan },{ msg: Chuck Norris },{ msg: Jet Li },{ msg: Kung Fury }]}},//注册局部组件components:{},//方法methods:{ //进入前触发事件beforeEnter: function (el) {el.style.opacity 0el.style.height 0},//进入时触发事件enter: function (el, done) {var delay el.dataset.index * 150setTimeout(function () {Velocity(el,{ opacity: 1, height: 1.6em },{ complete: done })}, delay)},//离开时触发事件leave: function (el, done) {var delay el.dataset.index * 150setTimeout(function () {Velocity(el,{ opacity: 0, height: 0 },{ complete: done })}, delay)}},//计算属性computed:{computedList: function () {var vm thisreturn this.list.filter(function (item) {return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) ! -1})}},//渲染dommounted:function(){ } } /script style scoped/style2.1.6 可复用的过渡 要创建一个可复用过渡组件你需要做的就是将 transition 或者 transition-group 作为根组件然后将任何子组件放置在其中就可以了。 简单组件代码示例 Vue.component(my-special-transition, {template: \transition\namevery-special-transition\modeout-in\v-on:before-enterbeforeEnter\v-on:after-enterafterEnter\\slot/slot\/transition\,methods: {beforeEnter: function (el) {// ...},afterEnter: function (el) {// ...}} }) 2.1.7 动态过渡 动态过渡最基本的例子是通过 name 属性 来绑定动态值。 transition v-bind:nametransitionName !-- ... -- /transition 当你想用 Vue 的过渡系统来定义的 CSS 过渡/动画在不同过渡间切换会非常有用。 所有过渡属性都可以动态绑定但我们不仅仅只有属性可以利用还可以通过事件钩子获取上下文中的所有数据因为事件钩子都是方法。这意味着根据组件的状态不同你的 JavaScript 过渡会有不同的表现。 实例代码 templatedivh3动态过渡/h3 Fade In: input typerange v-modelfadeInDuration min0 v-bind:maxmaxFadeDurationFade Out: input typerange v-modelfadeOutDuration min0 v-bind:maxmaxFadeDurationtransition v-bind:cssfalsev-on:before-enterbeforeEnterv-on:enterenterv-on:leaveleavep v-ifshowhello/p/transitionbutton v-ifstop v-on:clickstop false; show false开始动画/buttonbutton v-else v-on:clickstop true结束动画/button/div /template script import Velocity from velocity-animate; export default { //数据data(){return {show: true,fadeInDuration: 1000,fadeOutDuration: 1000,maxFadeDuration: 1500,stop: true}},//注册局部组件components:{},//方法methods:{ //进入前触发事件beforeEnter: function (el) {el.style.opacity 0},//进入时触发事件enter: function (el, done) {var vm thisVelocity(el,{ opacity: 1 },{duration: this.fadeInDuration,complete: function () {done();if (!vm.stop) {vm.show false;}}});},//离开时触发事件leave: function (el, done) {var vm this;Velocity(el,{ opacity: 0 },{duration: this.fadeOutDuration,complete: function () {done();vm.show true;}});}},//计算属性computed:{},//渲染dommounted:function(){ this.show false;} } /script style scoped/style2.2 过渡状态 Vue 的过渡系统提供了非常多简单的方法设置进入、离开和列表的动效。那么对于数据元素本身的动效呢比如 数字和运算颜色的显示SVG 节点的位置元素的大小和其他的 property 这些数据要么本身就以数值形式存储要么可以转换为数值。有了这些数值后我们就可以结合 Vue 的响应式和组件系统使用第三方库来实现切换元素的过渡状态。 2.2.1 状态动画与侦听器 通过侦听我们能监听到任何数值属性的数值更新首先我们先看一下通过监听数字文本框中数值变化从而实现数字动态变化的实例 首先执行npm i gsap3.2.4 命令安装gsap插件动画库与图片预览插件 实例代码 templatedivh3状态动画与侦听器/h3 input typenumber v-model.numbernumber step20/p{{ animatedNumber }}/p/div /template script import gsap from gsap; export default { //数据data(){return {number: 0,tweenedNumber: 0}},//注册局部组件components:{},//方法methods:{ },//计算属性computed:{animatedNumber:function(){return this.tweenedNumber.toFixed(0);}},//侦听watch:{number: function(newValue) {gsap.to(this.$data, { duration: 0.5, tweenedNumber: newValue });}},//渲染dommounted:function(){ } } /script style scoped/style对于不能直接像数字一样存储的值比如 CSS 中的 color 的值使用tween和color-js插件实现 1执行命令npm i tween 安装tween插件 2执行命令 npm i color-js 安装color插件 实例代码 templatedivh3状态动画与侦听器/h3 input v-modelcolorQuery v-on:keyup.enterupdateColor placeholder输入一个颜色button v-on:clickupdateColor更新/buttonpPreview:/pspan v-bind:style{ backgroundColor: tweenedCSSColor } classexample-7-color-preview/spanp{{ tweenedCSSColor }}/p/div /template script import TWEEN from tween; import Color from color-js;export default { //数据data(){return {colorQuery: ,colorData: {red: 0,green: 0,blue: 0,alpha: 1},tweenedColor: {}}},created: function () {this.tweenedColor Object.assign({}, this.colorData); },//注册局部组件components:{},//方法methods:{ //更新颜色updateColor: function () {this.colorData new Color(this.colorQuery).toRGB();this.colorQuery ;}},//计算属性computed:{tweenedCSSColor: function () {return new Color({red: this.tweenedColor.red,green: this.tweenedColor.green,blue: this.tweenedColor.blue,alpha: this.tweenedColor.alpha}).toCSS();}},//侦听watch:{colorData: function () {function animate () {if (TWEEN.update()) {requestAnimationFrame(animate);}}new TWEEN.Tween(this.tweenedColor).to(this.colorData, 750).start();animate();}},//渲染dommounted:function(){ } } /script style scoped.example-7-color-preview {display: inline-block;width: 50px;height: 50px;} /style2.2.2 动态状态过渡 就像 Vue 的过渡组件一样数据背后状态过渡会实时更新这对于原型设计十分有用。当你修改一些变量即使是一个简单的 SVG 多边形也可实现很多难以想象的效果。这里我们使用TweenLite实现一个缓动作的动态效果 1执行npm i gsap 安装插件 注TweenLite最初是GreenSock公司推出的一款基于ActionScript的免费开源的缓动引擎是webgame开发人员比较常用的一个动画库使用TweenLite能够简化动画制作的代码编写工作。TweenLite属于gsap插件中的一个模块详情参见官网GreenSock 实例代码 templatediv classsvgDivh3动态状态过渡/h3 svg width200 height200polygon :pointspoints/polygoncircle cx100 cy100 r90/circle/svglabelSides: {{ sides }}/labelinput typerange min3 max500 v-model.numbersides /labelMinimum Radius: {{ minRadius }}%/labelinput typerange min0 max90 v-model.numberminRadius /labelUpdate Interval: {{ updateInterval }} milliseconds/labelinput typerange min10 max2000 v-model.numberupdateInterval //div /template script import TweenLite from gsap; /** 数值转换坐标点*/ function valueToPoint(value, index, total) {var x 0;var y -value * 0.9;var angle ((Math.PI * 2) / total) * index;var cos Math.cos(angle);var sin Math.sin(angle);var tx x * cos - y * sin 100;var ty x * sin y * cos 100;return { x: tx, y: ty };}/**生成坐标点 */function generatePoints(stats) {var total stats.length;return stats.map(function(stat, index) {var point valueToPoint(stat, index, total);return point.x , point.y;}).join( );} export default { //数据data(){var defaultSides 10;//图形默认边数var stats Array.apply(null, { length: defaultSides }).map(function() {return 100;});return {stats: stats,points:generatePoints(stats),sides: defaultSides,//图形的边数minRadius: 50,//最小直径长度interval: null,updateInterval: 500//图形变动时长}},created: function () { },//注册局部组件components:{},//方法methods:{ //randomizeStats() {var vm this;this.stats this.stats.map(function() {return vm.newRandomValue();});},//根据最小直径随机生成图形大小newRandomValue() {return Math.ceil(this.minRadius Math.random() * (100 - this.minRadius));},//重置图形变动时间间隔resetInterval() {var vm this;clearInterval(this.interval);//清除定时器this.randomizeStats();this.interval setInterval(function() {vm.randomizeStats();}, this.updateInterval);}},//计算属性computed:{},//侦听watch:{//图形显示边数sides: function(newSides, oldSides) {let sidesDifference newSides - oldSides;if (sidesDifference 0) {for (let i 1; i sidesDifference; i) {this.stats.push(this.newRandomValue());}} else {let absoluteSidesDifference Math.abs(sidesDifference);for (let i 1; i absoluteSidesDifference; i) {this.stats.shift();}}},//图形动画stats: function(newStats) {TweenLite.to(this.$data, this.updateInterval / 1000, {points: generatePoints(newStats)});},//更新图形变动时间间隔updateInterval: function() {this.resetInterval();}},//渲染dommounted:function(){ this.resetInterval();} } /script style scopedsvg {display: block;}polygon {fill: #41b883;}circle {fill: transparent;stroke: #35495e;}input[typerange] {display: block;width: 100%;margin-bottom: 15px;}.svgDiv{width: 40%;margin: auto;} /style2.2.3 把过渡放到组件里 管理太多的状态过渡会很快的增加 Vue 实例或者组件的复杂性幸好很多的动画可以提取到专用的子组件。我们以数字文本输入改变动画为例写一个通用组件 实例代码 templatedivh3把过渡放到组件里/h3 input v-model.numberfirstNumber typenumber step20 input v-model.numbersecondNumber typenumber step20 {{ result }}panimated-integer v-bind:valuefirstNumber/animated-integer animated-integer v-bind:valuesecondNumber/animated-integer animated-integer v-bind:valueresult/animated-integer/p/div /template script import TWEEN from tween;//AnimateInteger子组件 var AnimateInteger{data:function(){return {tweeningValue:0}},props: {value: {type: Number,required: true}},methods:{tween: function (startValue, endValue) {var vm this;function animate () {if (TWEEN.update()) {requestAnimationFrame(animate);}}new TWEEN.Tween({ tweeningValue: startValue }).to({ tweeningValue: endValue }, 500).onUpdate(function () {vm.tweeningValue this.tweeningValue.toFixed(0);}).start();animate();}},//侦听watch: {value: function (newValue, oldValue) {this.tween(oldValue, newValue)}},//dom渲染mounted: function () {this.tween(0, this.value)},template:span{{ tweeningValue }}/span }; export default { //数据data(){return {firstNumber: 20,secondNumber: 40}},created: function () { },//注册局部组件components:{animated-integer:AnimateInteger},//方法methods:{ },//计算属性computed:{//计算结果result: function () {return this.firstNumber this.secondNumber;}},//侦听watch:{},//渲染dommounted:function(){ } } /script style scoped/style3.可复用性与组合 3.1 混入 混入 (mixin) 提供了一种非常灵活的方式来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时所有混入对象的选项将被“混合”进入该组件本身的选项。 那也就是说你可以单独写个逻辑文件默认导出一个对象对象里面可以包含data、created、mounted、methods 等vue模板文件中的逻辑对象。接着可以将这个对象引入到多个vue模板中进行功能复用从而达到功能模块的逻辑封装便于使用及后期维护。 3.1.1 基础 首先我们在项目src目录下创建mixins文件夹用于存放混入组件的文件 创建basemixins.js文件来实现一个基础混入代码 /**基础混入的使用 */ export default{methods: {hello: function () {console.log(hello from mixin!)}},created() {this.hello();} } vue页面中引入 basemixins.js代码 templatedivh3基础混入/h3 /div /template script import basemixin from /mixins/basemixins //引入js export default { mixins: [basemixin], // 使用混入 //数据data(){return {firstNumber: 20,secondNumber: 40}},created: function () { },//注册局部组件components:{},//方法methods:{ },//计算属性computed:{},//侦听watch:{},//渲染dommounted:function(){ } } /script style scoped/style运行项目查看控制台的输出 3.1.2 选项合并 当组件和混入对象含有同名选项时这些选项将以恰当的方式进行“合并”。 3.1.2.1 数据对象合并 数据对象在内部会进行递归合并并在发生冲突时以组件数据优先 创建seelctmixin.js代码 export default{data(){return{message:hello,foo:abc}} } vue页面中引入 seelctmixin.js代码 templatedivh3混入——选项合并之数据对象/h3 p{{message}}/pp{{foo}}/pp{{bar}}/p/div /template script import selectmixin from /mixins/selectmixin //引入js export default { mixins: [selectmixin], // 使用混入 //数据data(){return {message:hello world,foo:abc1234,bar:def}},created: function () { console.log(this.$data) },//注册局部组件components:{},//方法methods:{ },//计算属性computed:{},//侦听watch:{},//渲染dommounted:function(){ } } /script style scoped/style渲染效果 3.1.2.2 同名钩子函数合并 同名钩子函数将合并为一个数组因此都将被调用。另外混入对象的钩子将在组件自身钩子之前调用 seelctmixin.js代码 export default{created: function () {console.log(混入对象的钩子被调用)} } vue页面代码 templatedivh3混入——同名钩子函数合并/h3 /div /template script import selectmixin from /mixins/selectmixin //引入js export default { mixins: [selectmixin], // 使用混入 //数据data(){return {message:hello world,foo:abc1234,bar:def}},created: function () { console.log(组件钩子被调用) },//注册局部组件components:{},//方法methods:{ },//计算属性computed:{},//侦听watch:{},//渲染dommounted:function(){ } } /script style scoped/style运行项目查看控制台的输出 3.1.2.3 值为对象的选项合并 值为对象的选项例如 methods、components 和 directives将被合并为同一个对象。两个对象键名冲突时取组件对象的键值对。 seelctmixin.js代码 export default{methods: {foo() {console.log(foo)},conflicting() {console.log(from mixin)}} } vue页面代码 templatedivh3混入——值为对象的选项合并/h3 /div /template script import selectmixin from /mixins/selectmixin //引入js export default { mixins: [selectmixin], // 使用混入 //数据data(){return {message:hello world,}},created: function () { this.foo();this.bar();this.conflicting();},//注册局部组件components:{},//方法methods:{bar() {console.log(bar)},conflicting() {console.log(from self)} },//计算属性computed:{},//侦听watch:{},//渲染dommounted:function(){ } } /script style scoped/style运行项目查看控制台的输出 3.1.3 全局混入 混入也可以进行全局注册。使用时格外小心一旦使用全局混入它将影响每一个之后创建的 Vue 实例。使用恰当时这可以用来为自定义选项注入处理逻辑。 在main.js中定义一个全局混入代码 import Vue from vue import App from ./App.vue//引入根组件 import router from ./router/router.js//引用router.js import /assets/css/common.scss // 全局样式 import animate from animate.cssVue.use(animate) Vue.config.productionTip false; //实例化vue new Vue({router,render: h h(App),//导入根组件 }).$mount(#app);//mount挂载应用 根组件id // 为自定义的选项 myOption 注入一个处理器。 Vue.mixin({created:function(){var myOption this.$options.myOptionif (myOption) {console.log(myOption)}} }); vue页面代码 templatedivh3全局混入/h3 /div /template script export default { //数据myOption: hello!,data(){return {}},created: function () { },//注册局部组件components:{ },//方法methods:{},//计算属性computed:{ },//侦听watch:{},//渲染dommounted:function(){ } } /script style scoped/style运行项目查看控制台输出 请谨慎使用全局混入因为它会影响每个单独创建的 Vue 实例 (包括第三方组件)。大多数情况下只应当应用于自定义选项就像上面示例一样。推荐将其作为插件发布以避免重复应用混入。  3.1.4 自定义选项合并策略  自定义选项将使用默认策略即简单地覆盖已有值。如果想让自定义选项以自定义逻辑合并可以向 Vue.config.optionMergeStrategies 添加一个函数 Vue.config.optionMergeStrategies.myOption function (toVal, fromVal) { // 返回合并后的值 } 对于多数值为对象的选项可以使用与 methods 相同的合并策略 var strategies Vue.config.optionMergeStrategies strategies.myOption strategies.methods  可以在 Vuex 1.x 的混入策略里找到一个更高级的例子 const merge Vue.config.optionMergeStrategies.computed Vue.config.optionMergeStrategies.vuex function (toVal, fromVal) {if (!toVal) return fromValif (!fromVal) return toValreturn {getters: merge(toVal.getters, fromVal.getters),state: merge(toVal.state, fromVal.state),actions: merge(toVal.actions, fromVal.actions)} } 3.2 自定义指令 3.2.1 简介 除了核心功能默认内置的指令 (v-model 和 v-show)Vue 也允许注册自定义指令。注意在 Vue2.0 中代码复用和抽象的主要形式是组件。然而有的情况下你仍然需要对普通 DOM 元素进行底层操作这时候就会用到自定义指令。 这里我们以文本框输入聚焦为示例当页面加载时该元素将获得焦点 (注意autofocus 在移动版 Safari 上不工作)。事实上只要你在打开这个页面后还没点击过任何内容这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能 全局指令注册方式main.js代码 import Vue from vue import App from ./App.vue//引入根组件 import router from ./router/router.js//引用router.jsVue.config.productionTip false; //实例化vue new Vue({router,render: h h(App),//导入根组件 }).$mount(#app);//mount挂载应用 根组件id //注册全局v-focus指令 Vue.directive(focus, {// 当被绑定的元素插入到 DOM 中时……inserted: function (el) {// 聚焦元素el.focus()} }); vue页面中局部注册 代码 templatedivh3自定义指令——v-focus/h3input v-focus v-modelmessage /div /template script export default { //注册局部指令v-focusdirectives: {focus: {// 指令的定义inserted: function (el) {el.focus()}} }, //数据 data(){return {message:}} } /script style scoped/stylevue页面中input输入框直接使用v-focus指令即可 templatedivh3自定义指令——v-focus/h3input v-focus v-modelmessage /div /template script export default { //数据data(){return {message:}} } /script style scoped/style3.2.2 钩子函数 一个指令定义对象可以提供如下几个钩子函数 (均为可选) bind只调用一次指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted被绑定元素插入父节点时调用 (仅保证父节点存在但不一定已被插入文档中)。update所在组件的 VNode 更新时调用但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。componentUpdated指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind只调用一次指令与元素解绑时调用。 3.2.2.1 钩子函数参数 指令钩子函数会被传入以下参数 el指令所绑定的元素可以用来直接操作 DOM。binding一个对象包含以下 property name指令名不包括 v- 前缀。value指令的绑定值例如v-my-directive1 1 中绑定值为 2。oldValue指令绑定的前一个值仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。expression字符串形式的指令表达式。例如 v-my-directive1 1 中表达式为 1 1。arg传给指令的参数可选。例如 v-my-directive:foo 中参数为 foo。modifiers一个包含修饰符的对象。例如v-my-directive.foo.bar 中修饰符对象为 { foo: true, bar: true }。 vnodeVue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。oldVnode上一个虚拟节点仅在 update 和 componentUpdated 钩子中可用。 除了 el 之外其它参数都应该是只读的切勿进行修改。如果需要在钩子之间共享数据建议通过元素的 dataset 来进行。 现在我们使用钩子函数参数性质来自定义一个钩子 templatedivh3自定义指令——钩子函数自定义钩子/h3p v-demo:foo.a.bmessage/p/div /template script export default { //自定义钩子directives: {demo: {//钩子的定义bind: function (el, binding, vnode) {var s JSON.stringify;el.innerHTML name: s(binding.name) br value: s(binding.value) br expression: s(binding.expression) br argument: s(binding.arg) br modifiers: s(binding.modifiers) br vnode keys: Object.keys(vnode).join(, );}} },//数据data(){return {message:hello}} } /script style scoped/style3.2.2.2 动态指令参数 指令的参数可以是动态的。例如在 v-mydirective:[argument]value 中argument 参数可以根据组件实例数据进行更新这使得自定义指令可以在应用中被灵活使用。 这里我们通过用来通过固定布局将元素固定在页面上定义一个指令可以设定元素固定位置 templatedivh3自定义指令——动态指令参数/h3p v-pin:[direction]200I am pinned onto the page at 200px to the left./p/div /template script export default { //自定固定位置的动态指令directives: {pin: {bind: function (el, binding, vnode) {el.style.position fixed;var s (binding.arg left ? left : top);el.style[s] binding.value px;console.log(vnode);}} },//数据data(){return {direction: left}} } /script style scoped/style3.2.3 函数简写 在很多时候你可能想在 bind 和 update 时触发相同行为而不关心其它的钩子。比如这样写 Vue.directive(color-swatch, function (el, binding) {el.style.backgroundColor binding.value }) 3.2.4 对象字面量 如果指令需要多个值可以传入一个 JavaScript 对象字面量。 实例代码 templatedivh3自定义指令——对象字面量/h3p v-demo{ color: white, text: hello! }/p/div /template script export default { //对象字面量传参directives: {demo: {bind: function (el, binding) {el.innerHTMLbinding.value.color binding.value.text;}} },//数据data(){return {direction: left}},created: function () { },//注册局部组件components:{ },//方法methods:{},//计算属性computed:{ },//侦听watch:{},//渲染dommounted:function(){ } } /script style scoped/style3.3 渲染函数与JSX 3.3.1 基础 Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数它比模板更接近编译器。 这里我们通过生成带锚点的标题的组件为示例一个通过普通方式实现一个通过render渲染函数实现深入了解前后不同 普通方式实现 templatedivh3渲染函数/h3anchored-heading :level1h1标题/anchored-headinganchored-heading :level2h2标题/anchored-heading/div /template script //定义锚点标题组件——未使用渲染函数 var anchoredHeading{data:function(){return{}},methods:{},props: {level: {type: Number,required: true}},template:divh1 v-iflevel 1slot/slot/h1h2 v-else-iflevel 2slot/slot/h2h3 v-else-iflevel 3slot/slot/h3h4 v-else-iflevel 4slot/slot/h4h5 v-else-iflevel 5slot/slot/h5h6 v-else-iflevel 6slot/slot/h6/div }; export default { //数据data(){return {message: hello world}},//注册局部组件components:{ anchored-heading:anchoredHeading} } /script style scoped/style使用渲染函数实现 templatedivh3渲染函数/h3anchored-heading :level1h1标题/anchored-headinganchored-heading :level2h2标题/anchored-headinganchored-heading :level3h3标题/anchored-heading/div /template script //定义锚点标题组件——使用渲染函数 var anchoredHeading{data:function(){return{}},methods:{},props: {level: {type: Number,required: true}},render: function (createElement) {return createElement(h this.level, // 标签名称this.$slots.default // 子节点数组)},template:div/div }; export default { //数据data(){return {message: hello world}},//注册局部组件components:{ anchored-heading:anchoredHeading} } /script style scoped/style通过前后代码对比我们会发现没有使用渲染函数的代码要比使用渲染函数的代码更显的冗长 3.3.2 节点、树以及虚拟DOM 在深入渲染函数之前了解一些浏览器的工作原理是很重要的。 每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样每个节点都可以有孩子节点 (也就是说每个部分可以包含其它的一些部分)。 不同的节点就组成了树。 虚拟DOMVue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM。我们可通过createElement创建虚拟DOM,比如 return createElement(h1, this.blogTitle) createElement 到底会返回什么呢其实不是一个实际的 DOM 元素。它更准确的名字可能是 createNodeDescription因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点包括及其子节点的描述信息。我们把这样的节点描述为“虚拟节点 (virtual node)”也常简写它为“VNode”。“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼。 3.3.3 createElement参数 // returns {VNode} createElement(// {String | Object | Function}// 一个 HTML 标签名、组件选项对象或者// resolve 了上述任何一种的一个 async 函数。必填项。div,// {Object}// 一个与模板中 attribute 对应的数据对象。可选。{// (详情见下一节)},// {String | Array}// 子级虚拟节点 (VNodes)由 createElement() 构建而成// 也可以使用字符串来生成“文本虚拟节点”。可选。[先写一些文字,createElement(h1, 一则头条),createElement(MyComponent, {props: {someProp: foobar}})] ) 3.3.3.1 深入数据对象 有一点要注意正如 v-bind:class 和 v-bind:style 在模板语法中会被特别对待一样它们在 VNode 数据对象中也有对应的顶层字段。该对象也允许你绑定普通的 HTML attribute也允许绑定如 innerHTML 这样的 DOM property (这会覆盖 v-html 指令)。 {// 与 v-bind:class 的 API 相同// 接受一个字符串、对象或字符串和对象组成的数组class: {foo: true,bar: false},// 与 v-bind:style 的 API 相同// 接受一个字符串、对象或对象组成的数组style: {color: red,fontSize: 14px},// 普通的 HTML attributeattrs: {id: foo},// 组件 propprops: {myProp: bar},// DOM propertydomProps: {innerHTML: baz},// 事件监听器在 on 内// 但不再支持如 v-on:keyup.enter 这样的修饰器。// 需要在处理函数中手动检查 keyCode。on: {click: this.clickHandler},// 仅用于组件用于监听原生事件而不是组件内部使用// vm.$emit 触发的事件。nativeOn: {click: this.nativeClickHandler},// 自定义指令。注意你无法对 binding 中的 oldValue// 赋值因为 Vue 已经自动为你进行了同步。directives: [{name: my-custom-directive,value: 2,expression: 1 1,arg: foo,modifiers: {bar: true}}],// 作用域插槽的格式为// { name: props VNode | ArrayVNode }scopedSlots: {default: props createElement(span, props.text)},// 如果组件是其它组件的子组件需为插槽指定名称slot: name-of-slot,// 其它特殊顶层 propertykey: myKey,ref: myRef,// 如果你在渲染函数中给多个元素都应用了相同的 ref 名// 那么 $refs.myRef 会变成一个数组。refInFor: true } 有了以上关于渲染函数等知识我们现在写一个完整的示例 templatedivh3渲染函数——深入数据对象/h3anchored-heading :level1h1标题/anchored-headinganchored-heading :level2h2标题/anchored-headinganchored-heading :level3h3标题/anchored-heading/div /template script //获取子节点文本内容 var getChildrenTextContent function (children) {return children.map(function (node) {return node.children? getChildrenTextContent(node.children): node.text;}).join(); } //定义锚点标题组件——使用渲染函数 var anchoredHeading{data:function(){return{}},methods:{},props: {level: {type: Number,required: true}},render: function (createElement) {// 创建 kebab-case 风格的 IDlet headingId getChildrenTextContent(this.$slots.default).toLowerCase().replace(/\W/g, -).replace(/(^-|-$)/g, );return createElement(h this.level, // 标签名称[createElement(a, {attrs: {name: headingId,href: # headingId}}, this.$slots.default)]);},template:div/div }; export default { //数据data(){return {direction: left}},//注册局部组件components:{ anchored-heading:anchoredHeading} } /script style scoped/style3.3.3.2 约束 组件树中的所有 VNode 必须是唯一的。这意味着下面的渲染函数是不合法的 render: function (createElement) {var myParagraphVNode createElement(p, hi)return createElement(div, [// 错误 - 重复的 VNodemyParagraphVNode, myParagraphVNode]) } 如果你真的需要重复很多次的元素/组件你可以使用工厂函数来实现。例如下面这渲染函数用完全合法的方式渲染了 20 个相同的段落 render: function (createElement) {return createElement(div,Array.apply(null, { length: 20 }).map(function () {return createElement(p, hi)})) } 3.3.4 使用JavaScript代替模板功能 3.3.4.1 v-if 和v-for 只要在原生的 JavaScript 中可以轻松完成的操作Vue 的渲染函数就不会提供专有的替代方法。比如在模板中使用的 v-if 和 v-for ul v-ifitems.lengthli v-foritem in items{{ item.name }}/li /ul p v-elseNo items found./p 这些都可以在渲染函数中用 JavaScript 的 if/else 和 map 来重写 props: [items], render: function (createElement) {if (this.items.length) {return createElement(ul, this.items.map(function (item) {return createElement(li, item.name)}))} else {return createElement(p, No items found.)} } 3.3.4.2 v-model 渲染函数中没有与 v-model 的直接对应——你必须自己实现相应的逻辑 这就是深入底层的代价但与 v-model 相比这可以让你更好地控制交互细节 props: [value], render: function (createElement) {var self thisreturn createElement(input, {domProps: {value: self.value},on: {input: function (event) {self.$emit(input, event.target.value)}}}) } 3.3.4.3 事件与按键修饰符 对于 .passive、.capture 和 .once 这些事件修饰符Vue 提供了相应的前缀可以用于 on 修饰符前缀.passive.capture!.once~.capture.once 或.once.capture~! 例如 on: {!click: this.doThisInCapturingMode,~keyup: this.doThisOnce,~!mouseover: this.doThisOnceInCapturingMode } 对于所有其它的修饰符私有前缀都不是必须的因为你可以在事件处理函数中使用事件方法 修饰符处理函数中的等价操作.stopevent.stopPropagation().preventevent.preventDefault().selfif (event.target ! event.currentTarget) return按键.enter, .13if (event.keyCode ! 13) return (对于别的按键修饰符来说可将 13 改为另一个按键码)修饰键.ctrl, .alt, .shift, .metaif (!event.ctrlKey) return (将 ctrlKey 分别修改为 altKey、shiftKey 或者 metaKey) 这里是一个使用所有修饰符的例子 on: {keyup: function (event) {// 如果触发事件的元素不是事件绑定的元素// 则返回if (event.target ! event.currentTarget) return// 如果按下去的不是 enter 键或者// 没有同时按下 shift 键// 则返回if (!event.shiftKey || event.keyCode ! 13) return// 阻止 事件冒泡event.stopPropagation()// 阻止该元素默认的 keyup 事件event.preventDefault()// ...} } 3.3.4.4 插槽 你可以通过 this.$slots 访问静态插槽的内容每个插槽都是一个 VNode 数组 render: function (createElement) {// divslot/slot/divreturn createElement(div, this.$slots.default) } 也可以通过 this.$scopedSlots 访问作用域插槽每个作用域插槽都是一个返回若干 VNode 的函数 props: [message], render: function (createElement) {// divslot :textmessage/slot/divreturn createElement(div, [this.$scopedSlots.default({text: this.message})]) } 如果要用渲染函数向子组件中传递作用域插槽可以利用 VNode 数据对象中的 scopedSlots 字段 render: function (createElement) {// divchild v-slotpropsspan{{ props.text }}/span/child/divreturn createElement(div, [createElement(child, {// 在数据对象中传递 scopedSlots// 格式为 { name: props VNode | ArrayVNode }scopedSlots: {default: function (props) {return createElement(span, props.text)}}})]) } 3.3.5 JSX 如果你写了很多 render 函数可能会觉得下面这样的代码写起来很痛苦 createElement(anchored-heading, {props: {level: 1}}, [createElement(span, Hello), world!] ) 特别是对应的模板如此简单的情况下 anchored-heading :level1spanHello/span world! /anchored-heading 这就是为什么会有一个 Babel 插件用于在 Vue 中使用 JSX 语法它可以让我们回到更接近于模板的语法上。 import AnchoredHeading from ./AnchoredHeading.vuenew Vue({el: #demo,render: function (h) {return (AnchoredHeading level{1}spanHello/span world!/AnchoredHeading)} }) 将 h 作为 createElement 的别名是 Vue 生态系统中的一个通用惯例实际上也是 JSX 所要求的。从 Vue 的 Babel 插件的 3.4.0 版本开始我们会在以 ES2015 语法声明的含有 JSX 的任何方法和 getter 中 (不是函数或箭头函数中) 自动注入 const h this.$createElement这样你就可以去掉 (h) 参数了。对于更早版本的插件如果 h 在当前作用域中不可用应用会抛错。  了解关于更多JSX参见GitHub - vuejs/jsx-vue2: monorepo for Babel / Vue JSX related packages 3.3.6 函数式组件 之前创建的锚点标题组件是比较简单没有管理任何状态也没有监听任何传递给它的状态也没有生命周期方法。实际上它只是一个接受一些 prop 的函数。在这样的场景下我们可以将组件标记为 functional这意味它无状态 (没有响应式数据)也没有实例 (没有 this 上下文)。一个函数式组件就像这样 Vue.component(my-component, {functional: true,// Props 是可选的props: {// ...},// 为了弥补缺少的实例// 提供第二个参数作为上下文render: function (createElement, context) {// ...} }) 注意在 2.3.0 之前的版本中如果一个函数式组件想要接收 prop则 props 选项是必须的。在 2.3.0 或以上的版本中你可以省略 props 选项所有组件上的 attribute 都会被自动隐式解析为 prop。 当使用函数式组件时该引用将会是 HTMLElement因为他们是无状态的也是无实例的。 在 2.5.0 及以上版本中如果你使用了单文件组件那么基于模板的函数式组件可以这样声明 template functional /template 组件需要的一切都是通过 context 参数传递它是一个包括如下字段的对象 props提供所有 prop 的对象childrenVNode 子节点的数组slots一个函数返回了包含所有插槽的对象scopedSlots(2.6.0) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。data传递给组件的整个数据对象作为 createElement 的第二个参数传入组件parent对父组件的引用listeners(2.3.0) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。injections(2.3.0) 如果使用了 inject 选项则该对象包含了应当被注入的 property。 在添加 functional: true 之后需要更新我们的锚点标题组件的渲染函数为其增加 context 参数并将 this.$slots.default 更新为 context.children然后将 this.level 更新为 context.props.level。 因为函数式组件只是函数所以渲染开销也低很多。 在作为包装组件时它们也同样非常有用。比如当你需要做这些时 程序化地在多个组件中选择一个来代为渲染在将 children、props、data 传递给子组件之前操作它们。 下面是一个 smart-list 组件的例子它能根据传入 prop 的值来代为渲染更具体的组件 templatedivh3函数式组件/h3smart-list v-bindsmartDatassmart-list/smart-list/div /template script //定义组件——使用渲染函数 var smartList{functional: true,data:function(){return{}},methods:{},props: {level: {type: String,required: true},title: {type: String,required: true}},render:function (createElement, context) {// 子节点数组console.log(上下文:,context);let children [];// 属性获取的变化const {title,level} context.props;children children.concat(context.children);return createElement(hlevel,{ attrs: { title } },children)} }; export default { //数据data(){return {smartDatas:{level:1,title:hello world}}},//注册局部组件components:{ smart-list:smartList} } /script style scoped/style3.3.6.1 向子元素或子组件传递 attribute 和事件 在普通组件中没有被定义为 prop 的 attribute 会自动添加到组件的根元素上将已有的同名 attribute 进行替换或与其进行智能合并。 然而函数式组件要求你显式定义该行为 Vue.component(my-functional-button, {functional: true,render: function (createElement, context) {// 完全透传任何 attribute、事件监听器、子节点等。return createElement(button, context.data, context.children)} }) 通过向 createElement 传入 context.data 作为第二个参数我们就把 my-functional-button 上面所有的 attribute 和事件监听器都传递下去了。事实上这是非常透明的以至于那些事件甚至并不要求 .native 修饰符。 如果你使用基于模板的函数式组件那么你还需要手动添加 attribute 和监听器。因为我们可以访问到其独立的上下文内容所以我们可以使用 data.attrs 传递任何 HTML attribute也可以使用 listeners (即 data.on 的别名) 传递任何事件监听器。 template functionalbuttonclassbtn btn-primaryv-binddata.attrsv-onlistenersslot//button /template 3.3.6.2 slots() 和 children 对比  你可能想知道为什么同时需要 slots() 和 children。slots().default 不是和 children 类似的吗在一些场景中是这样——但如果是如下的带有子节点的函数式组件呢 my-functional-componentp v-slot:foofirst/ppsecond/p /my-functional-component 对于这个组件children 会给你两个段落标签而 slots().default 只会传递第二个匿名段落标签slots().foo 会传递第一个具名段落标签。同时拥有 children 和 slots()因此你可以选择让组件感知某个插槽机制还是简单地通过传递 children移交给其它组件去处理。
http://www.hkea.cn/news/14271004/

相关文章:

  • 公司网站建设好宁波网站建设的详细策划
  • 深圳福田车公庙网站建设自贡订房中心网站建设
  • 母婴护理服务网站模板wordpress自定义背景
  • 做公司网站的客户端app下载安装
  • 免费制作主图的网站市场推广是做什么的
  • 津南网站建设建网站_网站内容怎么做
  • 网站死链排查网络营销网站 功能
  • 上海市建设交通工会网站手表官网
  • 企业外贸营销型网站怎样自创网站
  • 网站制作模板广西网红排名
  • 知名网站建设公司排名溧阳城乡建设厅网站
  • 网站建设项目内容flash做网站的流程
  • 郑州做网站优化价格做网站必须用tomcat
  • 免费行情软件网站下载做个医院网站多少钱
  • 如何上传模板到网站招聘网站开发策划方案
  • 网站提交了被收录后改怎么做商业空间设计有限公司
  • 理查德西尔斯做的网站做平面设计兼职的网站
  • 网站开发那种语言网站建设与管理是课程
  • 陕西网站建设公司找哪家郑州网课老师
  • 做p2p网站 预算多少河南省今天刚刚人事调整最新
  • 个人网站设计教程网站推广方式措施
  • 东莞网站建设在线推广珠海模板建站定制网站
  • 网站建设一个购买链接开发网站开发工程师招聘要求
  • 网站产品演示wordpress上传excel文件
  • 国外做meta分析的网站北京市e窗口工商登记
  • 广州建设工程造价管理网站汕头建站培训
  • 金华高端网站建设公司网站建设的业务范围
  • 网站英文版是怎么做的wordpress浏览人数在哪里改
  • 站酷网在线官网静态网站建设规划
  • 网站设计费用志泰安焦点网络