用那种语言做网站比较好,wordpress中英文建站,记事本怎样做网站,wordpress 电台目录 一、入门案例 二、模板语法 三、数据绑定 四、el和data的两种写法 五、MVVM模型 六、Object.defineproperty方法 七、Vue中响应式原理 八、数据代理 九、methods配置项 十、Vue中的事件处理 十一、Vue中的键盘事件 十二、计算属性 十三、监视属性watch 十四、绑定Class样式… 目录 一、入门案例 二、模板语法 三、数据绑定 四、el和data的两种写法 五、MVVM模型 六、Object.defineproperty方法 七、Vue中响应式原理 八、数据代理 九、methods配置项 十、Vue中的事件处理 十一、Vue中的键盘事件 十二、计算属性 十三、监视属性watch 十四、绑定Class样式 十五、绑定style样式 十六、条件渲染 十七、列表渲染 十八、Key的原理以及diff算法 十九、列表过滤、排序 二十、过滤器 二十一、Vue如何监视data配置项 二十二、Vue如何监测数组 二十三、Vue.$set()方法 二十四、收集表单的value数据 二十五、v-text和v-html指令 二十六、v-cloak、v-once、v-pre指令 二十七、自定义指令directives 二十八、生命周期 一、入门案例 Vue可以看作是一个数据管理大师其目的通常是将其管理的数据展示到HTML页面上或者收集HTML页面上的数据进行储存在自身或者传递给服务器。 Vue管理的数据大致可以分为Ⅰ对象数据对象里面包含一些基本数据类型和嵌套着一些其他对象。Ⅱ数组Ⅲ函数。我们需要了解Vue是如何管理对象、数组、函数这3种数据类型包括如何响应式这些数据、如何代理这些数据等。 下面的代码是一个入门案例。首先引入vue.js的完整版引入vue.js之后在window上就多出了一个Vue构造函数对象使用new Vue()就可以创建一个Vue实例对象vm在创建vm的时候需要把希望给vm管理的数据通过data配置项交给vm把希望给vm管理的函数通过methods配置项交给vm。
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title初识vue/title!-- 引入Vue --script src../js/vue.js/script
/head
body!-- 准备好一个容器 --div idrooth1Hello{{name}}!/h1/divscriptVue.config.productionTip false // 阻止vue在启动时生成生产提示new Vue({el:#root, //el用于指定当前Vue实例为哪个容器服务值通常为css选择器字符串data:{ //data用于存储数据数据共el所指定的容器去使用name:么么哒}})/script
/body
/htmlvm实例在得到数据之后首先会进行一系列的加工然后把数据放到HTML页面上。所有需要告诉vm把数据放到哪个DOM节点。使用el配置项或者vm.$mount()就可以指定vm管理哪一个DOM节点(通常是div节点)。可以将一个字符串选择器或者一个DOM节点原始js对象交给el和$mount例如el:#root或者el:document.getElementByID(#root)。 在得到管理的模板之后就可以将数据展示到模板当中了。使用模板语法中的插值语法将管理的数据name使用{{name}}展示到模板页面当中。{{}}里面必须是js表达式这样才能够使用eval()函数进行运行识别同时{{}}里面可以直接使用vm管理的数据。
二、模板语法 1.插值语法使用双大括号{{}}可以在模板中插入变量或表达式的值。例如{{name}}。 2.指令语法Vue 提供了一些指令例如v-for、v-bind等。 他们的共同点就是{{js表达式}}或者v-bindjs表达式作用就是将vm管理的数据呈现到HTML模板页面上。js表达式除了原始js表达式之外还可以写vm自身管理的数据。 什么是js表达式答案执行之后能够得到具体值的语句。试想一下vm需要将数据展示到HTML页面当中如果你不通过函数return数据、或者表达式计算出数据来vm拿什么放到页面上面呢当然undefined不会被vm放入到页面当中。
三、数据绑定 数据绑定的本质就是1vm将数据放到页面称为单向绑定2一些表单节点可以采集数据vm可以对他们进行收集也可以把他们放到页面称为双向绑定。思考是否需要接触到DOM节点对象本身才能拿到这些数据呢 因为存在表单类DOM节点Vue不得已设计了两个指令来处理数据的绑定对于表单类节点例如input、select、textarea等使用v-model指令进行数据的双向绑定对于其他节点如div使用v-bind进行绑定。 v-bind可以简写为冒号。v-model默认收集表单节点的value属性那么可以使用v-model直接代替value也就是v-model:value可以简写为v-model。
四、el和data的两种写法 el一种是使用el配置项另一种是使用vm.$mount()方法。 data一种是直接传入一个对象另一种是使用函数函数return一个对象。使用函数返回是为了避免多个组件或者多个vm实例共用同一个data数据配置项。原因函数返回这种形式每次返回的data都是船新版本的对象而直接传入data由于引用传递的原因导致大家都在操作同一个data配置对象。
五、MVVM模型 Vue就是典型的MVVM架构M表示数据模型也就是对象{}、数组[]等原始js数据组织形式V就是view视图也就是HTML页面VM就是视图模型也就是vm实例或者vc组件实例负责数据管理和呈现。 六、Object.defineproperty方法 Object.defineproperty方法是Vue中实现数据代理和数据劫持的核心方法。但是不幸的是这个Object.defineproperty只能对对象的属性进行操作传入的第一个参数是对象而对象包装的属性有3种基本数据类型、对象、数组对象。 Object.defineproperty 的作用就是直接在一个对象上定义一个新属性或者修改一个已经存在的属性Object.defineproperty可以接收三个参数Object.defineproperty(obj, prop, desc)。obj : 第一个参数就是要在哪个对象身上添加或者修改属性prop : 第二个参数就是添加或修改的属性名desc 配置项一般是一个对象。 value给定的初始值 writable默认为控制属性是否可以被修改默认false configurable控制属性是否可以被删除默认false enumerable: 控制属性是否可以枚举true的话简单的说就是可以遍历获取该值默认false。 注意当使用了getter或setter方法不允许使用writable和value这两个属性(如果使用会直接报错滴)。原因都可以使用getter或setter方法了难道还能把value固定或者writable变为false不成 get 是获取值的时候的方法获取值的时候会被调用不设置时默认返回undefined。set 是设置值的时候的方法设置值的时候会被调用。get或set不是必须成对出现任写其一就可以。
七、Vue中响应式原理 Vue响应式的核心就是数据被修改了、被读取了Vue能够知道数据被修改或读取了。那只能依靠 Object.defineproperty这个API的set和get方法。而Object.defineproperty是针对对象属性的拿到一个对象不管这个对象嵌套了多深Vue都是进行遍历将每一个对象的属性套上set和get方法只有这样Vue才知道数据有没有被修改或者读取。 所以Vue无法直接处理数组对象因为只有数组的地址变了Vue才知道他所管理的这个数组被改变了如果只是修改数组里面的值Vue就无法进行监测也就是数组里面的数据变化Vue是不知道的所以Vue只能劫持重载数组对象的push、shift等方法才能知道数组里面的数据是否被修改。原因就是数组也是一个引用对象只要地址不变Vue就判断你没变即使数组里面的数据已经变化了。什么是数组内存里面连续的一段储存空间就是数组。 另外后面的数据不是通过data配置对象给的就只能通过vm.$set()方法把数据变成响应式。而且这种方式存在效率问题不管是线程执行时间还是内存消耗方面。
八、数据代理 什么是数据代理数据代理就是使用A对象对B对象的属性进行操作。在Vue中对象A就是vm对象B就是data配置项(vm上的_data对象)、computed上面的属性、methods中的方法。还有其他组件传递过来的props属性等。 Vue为什么使用vm去代理vm._data原因就是为了方便在模板语法当中或者vm实例当中可以直接使用vm._data上的数据。本质Vue中的数据代理本质上就是两次Object.defineproperty封装第一次是数据劫持第二次就是数据代理都是使用的 Object.defineproperty但是目的不一样。
九、methods配置项 methods是Vue的options的配置项对象中的一个属性其本身也是一个对象但是里面放的是函数。这些函数最终也会被vm进行代理从而可以通过vm去访问这些方法函数。这些方法一般写成普通函数以确保函数执行时的this指向vm或者vc。 而this的作用就是能够从指定对象身上拿到一些数据。 scriptVue.config.productionTip false new Vue({el:#root, data:{name:JOJO},methods:{showInfo1(event){console.log(event)},showInfo2(evnet,num){console.log(event,num)}}})/script
十、Vue中的事件处理 浏览器中的事件一般是通过浏览器的交互线程进行识别。浏览器的事件类型大致分为鼠标事件、键盘事件keydown、keyup、keypress、表单事件input、change、select、网页状态事件load、domcontextload、readystatechange等、焦点/剪贴板事件focus、blur等、窗口事件scroll、resize、touch事件等。每种事件类型的event对象都是不同的但是都存在currentTarget 、Target 、type三个属性以及preventDefault() 、stopPropagation()两个方法。 此外事件还分为HTML事件、DOM0级事件、DOM2级事件。Vue中使用的DOM0级事件也就给节点对应事件的回调从null改成Vue管理的函数或者其他地方的函数。因此vm实例销毁之后这些事件仍然存在。 当一个事件比如click由鼠标发出浏览器的事件识别线程识别到了鼠标按下然后生成一个事件对象event这个event对象取决于事件类型不同的事件类型的event对象是不一样的。就开始事件流先从document节点开始捕获到具体节点然后冒泡执行冒泡阶段所有被捕获的节点的事件都会被触发。 在Vue当中使用v-on事件名指令或者事件名称符号给节点绑定事件例如下面的代码。事件回调一般写在vm中的methods配置项当中。建议使用function关键字写成普通函数确保函数当中的this为vm或者vc。
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title事件的基本用法/titlescript src../js/vue.js/script
/head
bodydiv idrooth2hello,{{name}}/h2button v-on:clickshowInfo1点我提示信息1/buttonbutton clickshowInfo2($event,66)点我提示信息2/button/divscriptVue.config.productionTip false new Vue({el:#root, data:{name:JOJO},methods:{showInfo1(event){console.log(event)},showInfo2(evnet,num){console.log(event,num)}}})/script
/body
/html事件的参数传递问题首先clickdemo和clickdemo($event)等价。其次可以进行参数传递例如clickdemo(vm.a,123)。最后为了防止$event对象丢失可以使用clickdemo(vm.a,123,$event,345)进行占位置在回调函数的地方的第三个位置接收$event即可。 事件修饰符click.self.once.passive.capture.stop.preventdemo一共6个。self表示event的target是当前节点也就是event.currenttaargettarget时触发once只触发一次passive表示事件的默认行为(例如交互渲染行为立即执行无需等待回调执行完毕capture表示在捕获阶段执行回调stop表示阻止事件冒泡prevent表示阻止事件默认行为。
十一、Vue中的键盘事件 键盘事件使用很多很频繁。键盘事件包括三种keyup所有按键都能触发(例如A、B、C和win键)keydown同keyupkeypress按下有值的键时触发即按下 Ctrl、Alt、Shift、Meta 这样无值的键这个事件不会触发。对于有值的键按下时先触发keydown事件再触发这个keyup事件。 一些常见的键盘事件keydown.left、keydown.enter、keydown.13、keydown.esc等。 组合键盘事件比如CTRLC我们CV代码时小拇指会摁住CTRL不放然后不断地摁C和V因此组合键盘事件配合CTRL的keypress和其他键的keyup使用比如ctrl.sctrl.v。 自定义键码Vue.config.keyCodes.自定义键名 键码可以自定义按键别名例如Vue.config.keyCodes.A 666.
十二、计算属性 计算属性是Vue中的一个配置项用于实时的加工已有的数据。一是要满足实时性、二只能处理已经存在的数据(指数据当前已经在内存里面存在了)。实时性是因为加工得到的数据可能会放置到HTML页面当中也可能是其他数据链会依赖当前加工的数据所以需要速度快不要异步获取数据否则卡住主线程。 div idapp姓input typetext v-model:valuefirstNamebr/名input typetext v-model:valuelastNamebr/全名span{{fullName}}/span/divscriptconst vm new Vue({el:#app,data:{firstName:wang,lastName:y},computed:{fullName:{get(){return this.firstName-this.lastName;},set(value){const arr value.split(-);this.firstNamearr[0];this.lastNamearr[1];}}// 如果没有set函数可以采用如下的简写形式// fullName(){// return this.firstName-this.lastName;// }}});/script 计算属性的用法简写形式时把函数名当作属性使用。 计算属性的底层依靠的是Object.defineProperty()方法提供的getter和setter。也就是使用vm代理这些方法(显示的提供Object.defineProperty()给程序员使用)。另外能够自动识别所使用数据的变化但使用的数据发生变化自动更新属性值。 计算属性能够使用的数据vm自身的数据字面量数据等最好处理的数据都是响应式数据。其次计算属性是响应式数据 计算属性的思考计算属性在语法层面是一个函数或者一个对象。而且他是一个被Vue管理的响应式函数当其数据链中的响应式数据变化计算属性computed就会自动重新计算说明computed计算属在底层被放置在其所使用数据链路中数据的set中。 计算属性的调用时机1、get函数在初次读取时会执行一次2、当计算属性所依赖的响应式数据发生改变的时候get()函数会被再次调用。 计算属性的优势与methods实现相比计算属性采用了缓存机制脏值检测在获取计算属性的属性值时若所依赖的属性没有发生变化那么就不会执行get()函数而是将缓存的计算属性值返回。与methods每次都会执行计算逻辑相比效率更高。 底层原理2计算属性被Vue中的Watcher类进行封装当监听的属性发生变化也就是数据链上的数据发生变化时自动更新整条数据链。 计算属性最重要的就是其返回值。
十三、监视属性watch 监视属性是一个配置项是一个Vue进行管理的函数其主要作用就是监视数据有没有发生变化那么就可以肯定监视的数据必须是响应式数据也就是被Vue通过set()劫持过的数据某个数据可以被挂载在多个对象上实现多重响应式也就是多个监视点。 计算属性也可以被监视因为计算属性也是被响应式的数据。此外data配置项中的多级嵌套对象的属性也可以进行监视比如:school.namefunction(){}。总的来说只要是vm身上的响应式数据都可以进行监视且成功地运行响应式就是换一个对象进行监视多个对象监视同一个数据。 其目的是当数据发生变化就去执行相应的handler函数。然后通过handler函数去执行一些其他逻辑比如修改vm的数据、给vm添加新的响应式数据等同时刷新数据链和执行相关的渲染函数。 div idapph3今天天气很{{info}}/h3button clickchangeWeather()切换天气/button/divscriptconst vm new Vue({el:#app,data:{isHot:true,},computed:{info:{get(){return this.isHot?炎热:凉爽}}},methods: {changeWeather(){this.isHot !this.isHot}},// 监视写法一// watch:{// // 完整写法// // isHot:{// // // immediate:true, // 该参数设置为true可以在初始化的时候让handler调用一下 // // // deep:true, // 深度监视// // // 属性变化的回调函数// // handler(newValue,oldValue){// // console.log(属性isHot被修改了,newValue,oldValue);// // },// // },// // 简写形式// // 当我们监视的配置属性只有handler()函数不需要设置deep和immediate时可以采用简写形式// isHot(newValue,oldValue){// console.log(属性isHot被修改了,newValue,oldValue);// }// }});// // 正常写法// vm.$watch(isHot,{// // immediate:true, // 该参数设置为true可以在初始化的时候让handler调用一下 // // deep:true, // 深度监视// // 属性变化的回调函数// handler(newValue,oldValue){// console.log(属性isHot被修改了,newValue,oldValue);// }// });// 简写形式vm.$watch(isHot,function(newValue,oldValue){console.log(属性isHot被修改了,newValue,oldValue);})/script 监视属性的两种写法 第一种通过watch配置项这种分为简写和详细写详细写就是写成一个对象形式对象里面写3个配置属性deep、immediate、和handler回调。如果不要求deep和immediate那么就可以简写为函数形式ishot(isHot(newValue,oldValue)){}。 第二种通过vm.$watch()如上面的代码写法和watch配置项一模一样。 对于deep默认为false当监视的数据是一个多层嵌套的对象时可以开启deep为true这样不管嵌套多深的对象发生数据变化都可以被监视到。 对于immediate当被监视属性的回调函数注册到vm身上时立即执行一次。 回调函数的分类什么时候写成普通函数什么时候写成箭头函数答案就是handler只能写成普通函数才能确保this指向vm或者vc。 如果回调函数不需要将一些任务函数放到异步队列当中写成普通函数这样this就是vm或者vc此时的watch和computed效果上等价。如果回调函数handler里面使用了异步任务的回调函数需要扔到消息队列当中在将来的某个时刻拿到数据那么handler里面的回调需要写成箭头函数。 原因就是vm只是管理的handler函数当运行handler时才会生成handler方法体里面的箭头函数此时这些箭头函数是在vm对象的方法栈生成的所以handler方法体里面的回调函数的this就是vm或者vc。 注意function关键字生成的函数对象在生成的时候就指定this了也就是handler函数里面的function定义的函数在handler方法栈运行生成且被直接调用 的时候默认this为window这就是为什么handler()函数里面的内嵌回调函数不能写成普通函数的原因。
十四、绑定Class样式 DOM节点的class属性本质上是一个字符串多个类使用空格进行隔开空格两边就是类名所以Vue绑定class样式的本质就是通过已有的数据和条件动态修改class属性的字符串。 Vue绑定class的前提之一就是对应的类选择器样式已经存在。 情况一添加一个class属性使用:classvm身上的字符串类名就可以最终Vue整合所有的class之后放入到DOM节点当中。这里的js表达式可以是字面量字符串也可以是vm身上的数据。
div idroot!-- 绑定class样式--字符串写法适用于样式的类名不确定需要动态指定 --div classbasic :classmood clickchangeMood{{name}}/div br/br/!-- 绑定class样式--数组写法适用于要绑定的样式个数不确定、名字也不确定 --div classbasic :classclassArr{{name}}/div br/br/!-- 绑定class样式--对象写法适用于要绑定的样式个数确定、名字也确定但要动态决定用不用 --div classbasic :classclassObj{{name}}/div br/br/!-- 绑定style样式--对象写法 --div classbasic :stylestyleObj{{name}}/div br/br/!-- 绑定style样式--数组写法 --div classbasic :stylestyleArr{{name}}/div
/div情况二绑定多个类样式。这种情况下可以使用数组[]将所有的类名放在一起然后Vue自动将里面的字符串组合在一起放在DOM节点当中。也就是:class[vm.a,vm.b,vm.c]v-bind遇到class时自动合成字符串。 情况三:classobj根据obj对象里面的值来确定哪些类名被整合到最终的字符串当中这个obj中的key一般是vm身上的属性value一般是false和true。
script typetext/javascriptVue.config.productionTip falseconst vm new Vue({el:#root,data:{name:尚硅谷,mood:normal,classArr:[atguigu1,atguigu2,atguigu3],classObj:{atguigu1:false,atguigu2:false,},})
/script十五、绑定style样式 style样式和class样式如出一辙最终都是变成一个字符串。但是style样式的字符串是以key:value的形式表现的。所以style通常绑定一个vm所管理的js对象。例如:style{fontSize:xx}其中xx是vm身上的数据。而且Key必须是小驼峰写法默认是css的样式名称。 第二种情形就是使用数组例如style[styleobj1,styleobj2]其中styleobj1,styleobj2是vm身上的数据对象。
script typetext/javascriptVue.config.productionTip falseconst vm new Vue({el:#root,data:{name:尚硅谷,styleObj:{fontSize: 40px,color:red,},styleObj2:{backgroundColor:orange},styleArr:[{fontSize: 40px,color:blue,},{backgroundColor:gray}]},})
/script十六、条件渲染 条件渲染的目的就是从多个DOM节点中选择一个进行展示这种就是v-ifv-if-elsev-else等指令。
!DOCTYPE html
htmlheadmeta charsetUTF-8 /title条件渲染/titlescript typetext/javascript src../js/vue.js/script/headbodydiv idrooth2当前的n值是:{{n}}/h2button clickn点我n1/buttonh2 v-showtrueHello,{{name}}!/h2div v-ifn 1Angular/divdiv v-else-ifn 2React/divdiv v-elseVue/div/div/bodyscript typetext/javascriptVue.config.productionTip falseconst vm new Vue({el:#root,data:{name:jojo,n:0}})/script
/html另一种就是决定某一个DOM节点是否进行展示这就是v-show指令。这种方式的DOM的display变成None就被隐藏。 v-if写法v-if表达式 v-else-if表达式 v-else。适用于切换频率较低的场景。特点不展示的DOM元素直接被移除。注意v-if可以和v-else-if、v-else一起使用但要求结构不能被打断 v-show写法v-show表达式。适用于切换频率较高的场景。特点不展示的DOM元素未被移除仅仅是使用样式隐藏掉。
十七、列表渲染 列表渲染的本质是将Vue管理的容器数据通过循环展示到HTML页面上。Vue管理的容器类数据包括字符串、数组、嵌套对象等。列表渲染循环生成的同一个类型的DOM节点然后放入到模板当中。此时就需要使用:key这个预占的属性给Vue进行区分唯一的DOM节点。 一般语法为(value,id) in 容器。然后value和id就可以在模板语法当中使用。
!DOCTYPE html
htmlheadmeta charsetUTF-8 /title基本列表/titlescript typetext/javascript src../js/vue.js/script/headbodydiv idrooth2人员列表遍历数组/h2ulli v-for(p,index) in persons :keyindex{{p.name}}-{{p.age}}/li/ulh2汽车信息遍历对象/h2ulli v-for(value,k) in car :keyk{{k}}-{{value}}/li/ulh2遍历字符串/h2ulli v-for(char,index) in str :keyindex{{char}}-{{index}}/li/ulh2遍历指定次数/h2ulli v-for(number,index) in 5 :keyindex{{index}}-{{number}}/li/ul/divscript typetext/javascriptVue.config.productionTip falsenew Vue({el:#root,data:{persons:[{id:001,name:张三,age:18},{id:002,name:李四,age:19},{id:003,name:王五,age:20}],car:{name:奥迪A8,price:70万,color:黑色},str:hello}})/script/body
/htmlv-for指令用于展示列表数据
语法li v-for(item, index) in xxx :keyyyy其中key可以是index也可以是遍历对象的唯一标识可遍历数组、对象、字符串用的少、指定次数用的少
十八、Key的原理以及diff算法 Vue的vm实例一共管理着3个DOM对象分别是他的模板对应的真实DOM、真实DOM的备份、以及重新生成的新的DOM后两个可以看成是虚拟DOM只要后面两个DOM的DOM树的叶子或者节点不一样那么就会通过渲染函数重新更新真实DOM。 使用列表渲染时会生成新的节点这些节点不是一开始在模板当中写的属于后来的DOM节点所以需要特殊管理。 列表渲染新生成的DOM节点一般是一棵子DOM树使用key可以记录这棵子树的根节点diff差分算法就是根据从这个子树的根节点开始进行对比判断DOM节点是否发生变化。 如果发现key不存在直接创建新的子树。 如果key存在则会对子树遍历。但是对于一些真实DOM中存在的内容比如input框里面的内容Vue是不知道的因为Vue只有一开始真实DOM的备份后面这个真实DOM发生了什么变化Vue是不知道的。这就会导致真实DOM的一部分被替换掉而另外一部分还是残留的老的真实DOM。 如果遍历容器时使用index作为key则会出现部分真实DOM残留的问题。实际开发中一般使用独一无二的index作为key。 十九、列表过滤、排序 列表过滤和排序的本质对容器里面的数据进行筛选然后将筛选得到的新容器的数据放到页面上。那么进行筛选必然会产生新的临时容器。
!DOCTYPE html
htmlheadmeta charsetUTF-8 /title列表过滤/titlescript typetext/javascript src../js/vue.js/script/headbodydiv idrooth2人员列表/h2input typetext placeholder请输入名字 v-modelkeyWordulli v-for(p,index) of filPersons :keyindex{{p.name}}-{{p.age}}-{{p.sex}}/li/ul/divscript typetext/javascriptVue.config.productionTip falsenew Vue({el:#root,data:{keyWord:,persons:[{id:001,name:马冬梅,age:19,sex:女},{id:002,name:周冬雨,age:20,sex:女},{id:003,name:周杰伦,age:21,sex:男},{id:004,name:温兆伦,age:22,sex:男}]},computed:{filPersons(){return this.persons.filter((p){return p.name.indexOf(this.keyWord) ! -1})}}})/script/body
/html二十、过滤器 过滤器本质上就是数据二次加工的一些方法函数。其目的就是在数据真正放入HTML页面之前进行最后一步处理例如格式化字符串等。 这些方法和函数必须注册到vm身上才能使用有两种方法第一种使用fliters局部过滤器。第二种使用Vue.fliter这个API注册为全局过滤器所有vm和vc实例都可以使用。 Vue.fliter这个API注册过滤器函数的第一个参数是过滤名称第二个参数是对于的回调这个回调函数可以接受一个参数就是管道符|前面的vm身上的数据或者字面量。 对于局部过滤器直接把函数名当作过滤器名称。 过滤器的一般用法在模板语法当作数据后面使用管道符|过滤器名称。
!DOCTYPE html
htmlheadmeta charsetUTF-8 /title过滤器/titlescript typetext/javascript src../js/vue.js/scriptscript srchttps://cdn.bootcdn.net/ajax/libs/dayjs/1.10.6/dayjs.min.js/script/headbodydiv idrooth2时间/h2h3当前时间戳{{time}}/h3h3转换后时间{{time | timeFormater()}}/h3h3转换后时间{{time | timeFormater(YYYY-MM-DD HH:mm:ss)}}/h3h3截取年月日{{time | timeFormater() | mySlice}}/h3/div/bodyscript typetext/javascriptVue.config.productionTip false//全局过滤器Vue.filter(mySlice,function(value){return value.slice(0,11)})new Vue({el:#root,data:{time:1626750147900,},//局部过滤器filters:{timeFormater(value, strYYYY年MM月DD日 HH:mm:ss){return dayjs(value).format(str)}}})/script
/html二十一、Vue如何监视data配置项 新建一个Vue实例对象时我们传入了一个data配置对象然后它变成了vm身上的_data对象。那么Vue到底对这个data做了什么手脚呢原始的data对象又变成了什么样子 data对象里面无非状态三种东西基本数据类型、嵌套对象、数组。首先Vue使用Observe对象不断地遍历data对象如果他的属性是基本数据类型那么set/get走一波。如果是数组则进行重写数组的各种方法。如果还是对象则继续重复上面的过程。 data被Observe进行包装之后就得到_data对象然后原始的data又会指向_data对象。然后vm对_data对象进行数据代理。 这样就会存在一个问题后添加到vm身上的数据没有被set/get进行包装不具有响应式特性。那么可以使用Vue.$set()或者vm.$set()将后面的数据变成响应式。变成响应式的过程必然要找到一个可以依赖的对象(object.defineproperty的第一个参数所决定的)那么这个可以依赖的对象不能是vm也不能是_data更不能是window。他必须是data里面的一个对象且这个对象必然是响应式的。
二十二、Vue如何监测数组 一般来说数组作为的是data对象里面的一个属性使用Object.defineproperty将数组变成响应式的时候只要这个数组的堆内存地址不发生改变就无法监测数组里面的内容是否发生改变。那么Vue是如何监测数组里面内容的改变的呢 包装数据永不过时。对于数组对象我们重写数组的pop、push、shift、unshift、slice、sort、reverse方法。当vm拿到原生js数组之后给这个数组穿上马甲以push为例调用push时会去找穿了马甲的数组的push方法这个push一方面往数组里面加东西另一方面去执行对于的渲染函数由此实现数组的响应式。 对于通过data配置项对象传进去的数组如此但是对于后面添加的新的数组也是如此。
二十三、Vue.$set()方法 Vue.set和vm.$set都可以把后面来的数据变成响应式数据这些后来的数据包括数组、基本数据类型、对象、多层级嵌套对象。 这个API的原型是Vue.$set(target,key,value)。 其中target必须是一个对象这是由Object.defineproperty所决定的且这个target必须是vm身上的一个响应式对象。但不能是vm身上的根响应式对象实际上可以但是Vue做了if的判断禁止这么做。 第二个key必须是可哈希的在js语法当种就只能是数值和字符串。 第三个value就是key所对应的值。
二十四、收集表单的value数据 对于一个form表单里面存在input、select、textarea等表单元素对于这些DOM元素他们是特殊的。对input来说他的value就是输入框里面的值而且这个值还随着input的type不同而不同例如number、password、checkbox等那么他们的value的个数和类型也会不同。 对于Vue的v-model来说他主要搜集表单元素的value值由于表单的value值个数和类型是不确定所以vue针对不同的表单类型进行了处理使用不同的数据类型去接收不同个数和类型的表单的value值。总结每个表单元素都得初始化value属性对于多个value值vm使用数组进行接收。 若input typetext/则v-model收集的是value值用户输入的内容就是value值 若input typeradio/则v-model收集的是value值且要给标签配置value属性 若input typecheckbox/1.没有配置value属性那么收集的是checked属性勾选 or 未勾选是布尔值2.配置了value属性v-model的初始值是非数组那么收集的就是checked勾选 or 未勾选是布尔值v-model的初始值是数组那么收集的就是value组成的数组 v-model的三个修饰符lazy失去焦点后再收集数据number输入字符串转为有效的数字trim输入首尾空格过滤。
二十五、v-text和v-html指令 用于向其所在的DOM节点中插入文本也就是给DOM.innertext进行赋值。赋值数据来源就是vm所管理的数据或者网络请求得到的数据。
!DOCTYPE html
htmlheadmeta charsetUTF-8 /titlev-text指令/titlescript typetext/javascript src../js/vue.js/script/headbodydiv idrootdiv你好{{name}}/divdiv v-textname/divdiv v-textstr/div/div/bodyscript typetext/javascriptVue.config.productionTip false new Vue({el:#root,data:{name:JOJO,str:h3你好啊/h3}})/script
/html而v-html指令则是在当前节点append一个新的节点会把数据当作元素HTML处理。
二十六、v-cloak、v-once、v-pre指令 由于网络卡顿的原因当HTML页面已经渲染到页面窗口但是js脚本还没有运行页面就会展示还没有经过Vue处理的页面。这个时候可以给vm绑定模板添加v-cloak指令然后css样式将含有v-cloak属性的元素变为隐藏当模板被vue接管并mount之后删掉v-cloak属性模板就呈现到页面之上了。 v-once指令当前DOM只经过vue管理一次Vue就会放弃对这个节点的管理。 v-pre指令对于不包含vue模板语法的dom元素给他们加上v-pre那么vue就会在编译模板时忽略这些HTML元素。
v-cloak指令没有值 本质是一个特殊属性Vue实例创建完毕并接管容器后会删掉v-cloak属性使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
v-once指令 v-once所在节点在初次动态渲染后就视为静态内容了 以后数据的改变不会引起v-once所在结构的更新可以用于优化性能
v-pre指令
跳过其所在节点的编译过程。可利用它跳过没有使用指令语法、没有使用插值语法的节点会加快编译
二十七、自定义指令directives 通过上面对Vue指令的学习我们可以知道Vue指令不仅能修改DOM元素innerText内容还能修改innerHTML内容由此可知这些指令铁定拿到了对应的DOM元素。 另外例如v-bind指令v-bind:classarr指令还能根据里面的表达式得到具体的数据。那么指令是如何运行这里面的js表达式的 最后指令可以直接触摸到DOM节点那么指令和生命周期又有什么关系呢对于v-on绑定事件指令所有vm对象都可以使用那么能不能自定义只针对与某个vm自己使用的指令答案是可以的。 本质上来说指令就是将vm身上的数据通过操作DOM节点把vm身上的数据放到HTML页面的过程。而Vue是存在虚拟DOM的所以这些指令一直操作的都是虚拟DOM操作完毕之后再真正地展现到HTML页面当中。 注册局部指令可以使当前的vm或者vc实例对象使用自定义指令注册全局指令在Vue构造函数身上所有的vm和vc实例都可以使用这些指令。 局部指令注册方法如下 new Vue({ directives:{指令名:配置对象} }) new Vue({ directives:{指令名:回调函数} }) 全局指令注册方法如下所有的vm和vc都可以使用。
Vue.directive(指令名,配置对象)
Vue.directive(指令名,回调函数) 有两种声明一种是函数式声明一种是配置对象声明。函数式声明的调用时机1.指令与元素成功绑定时一上来 2.指令所在的模板被重新解析时也就是函数式声明只会执行bind回调函数和update函数。
!DOCTYPE html
htmlheadmeta charsetUTF-8 /title自定义指令/titlescript typetext/javascript src../js/vue.js/script/head!-- 需求1定义一个v-big指令和v-text功能类似但会把绑定的数值放大10倍。需求2定义一个v-fbind指令和v-bind功能类似但可以让其所绑定的input元素默认获取焦点。--bodydiv idrooth2当前的n值是span v-textn/span /h2h2放大10倍后的n值是span v-bign/span /h2button clickn点我n1/buttonhr/input typetext v-fbind:valuen/div/bodyscript typetext/javascriptVue.config.productionTip falsenew Vue({el:#root,data:{n:1},directives:{//big函数何时会被调用1.指令与元素成功绑定时一上来 2.指令所在的模板被重新解析时big(element,binding){console.log(big,this) //注意此处的this是windowelement.innerText binding.value * 10},fbind:{//指令与元素成功绑定时一上来bind(element,binding){element.value binding.value},//指令所在元素被插入页面时inserted(element,binding){element.focus()},//指令所在的模板被重新解析时update(element,binding){element.value binding.value}}}})/script
/html在新的DOM被放到HTML页面上之前所有指令对虚拟DOM的操作都应该被完成。在操作DOM之前首先要确定指令与虚拟DOM当中某个节点的联系也就是bind所以当指令与模板中某个DOM节点绑定时就会执行bind回调。 由于Vue是数据驱动的数据变化模板也会变化所以当vm管理的数据发生变化时对应的指令就会执行去修改虚拟DOM然后进行diff然后放到HTML页面。所以只要vm的数据发生改变该模板上的所有指令都会被重新执行然后得到最终的虚拟DOM。 细说element和binding 这两个在回调函数当中的对象element表示该指令所绑定的模板中的DOM节点对象binding对象是一个上下文信息对象他记录的有js表达式字符串和指令名称等然后使用eval函数执行得到value值这个value值在binding身上即需要展现到HTML页面上的数据都在binding身上。 对于有些页面效果或者默认行为需要DOM节点在HTML页面当中已经呈现了才能进行展示比如focus得等到那个节点在页面上了之后才能有获取焦点这个效果。所有指令还提供了update回调他的作用就是当页面已经呈现到HTML页面之后执行的回调相当于挂载DOM之后再次挂在一次保证虚拟DOM被挂载到页面再去执行focus获取焦点。 细说bind、inserted、update首先bind、inserted、一上来就会被执行也就是第一次生成虚拟DOM和将虚拟DOM放入HTML页面然后后面就不会执行了第二次、第三次把虚拟DOM放入HTML页面时只会执行update回调函数。所以功能上inserted、update是一致的只不过inserted只执行一次。而且这三个回调也称为钩子hook但是与生命周期的hook有显著差异。 一些注意点1模板语法当中指令使用-分割例如v-big-number。但是注册指令的时候多个单词的指令使用可哈希字符串big-number且不加v。2hook回调函数种的this皆是window而不是vm或者vc因为数据已经通过binding传递过来了而且element天然属于window的document而且还能防止通过this穿透恶意修改vm中的数据。
二十八、生命周期 生命周期就是vm实例从生成、渲染模板、销毁的整个过程然后在一些特殊时刻调用对应的钩子函数。这些函数主要用于修改vm或者vc身上的数据添加或者删除自定义事件等操作。由于这个原因生命周期当中的钩子函数中的this都是vm或者vc自身这样才能拿到vm或者vc身上的数据和其他的一些东西。 下面的图是Vue各个生命周期所需要做的事 思考vm的整个流程 1、一切都从new Vue开始短期目标就是成为一个数据管理大师首先就是初始化所有的生命周期钩子函数类似多少岁上学、多少岁结婚这就是beforecreated然后就是先把data穿上马甲变成自己的再把methods穿上马甲变成自己的这就是created此时空有数据但是没地方放数据。 2、等待有缘人等待一个模板能够被自己接管或者被vc组件接受。 3、成功入职。得到模板之后把自身的数据通过各种指令生成一个虚拟DOM。等待被展示这就是beforedmounted。 4、得到展示到HTML页面的机会将虚拟DOM成功放入HTML中mounted成功。 5、牛马一生阶段1。自己的数据不断被修改、不断地增加数据、删减数据然后被各种指令进行修改不断地得到新的虚拟DOM但是还得老板同意之后才能再次放入HTML页面这就是beforeupdated。 6、牛马一生阶段2。老板同意修改之后的虚拟DOM上线updated成功。然后在beforeupdated和updated不断地循环重复。 7、被老板辞掉了。准备跟老板吵架打算删库跑路beforedestoryed。 8、干不过老板destoryed完毕。 总结来说Vue生命周期钩子是一些函数他们在特殊的时刻点被自动的调用。由此可知当vm被创建之处必须先初始化各种钩子函数(也就是需要生成函数对象)。这些函数的作用就是在特殊时刻点执行一些动作例如CRUD数据、添加组件、自定义事件、删除自定义事件等。 另外这些生命周钩子一般当作的是Vue的配置项与data、methods同层次。