Vue.js - Day1
Node(后端)中的 MVC 与 前端中的 MVVM 之间的区别
-
MVC 是后端的分层开发概念;
-
MVVM是前端视图层的概念,主要关注于 视图层分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View , VM (ViewModel)
-
为什么有了MVC还要有MVVM
Vue.js 基本代码 和 MVVM 之间的对应关系
Vue之 - 基本的代码结构
和插值表达式
、v-cloak
1.el
指定要控制的区域
2.data
是个对象,指定了控制的区域内要用到的数据
3.methods
虽然带个s后缀,但是是个对象,这里可以自定义了方法
4.在 VM 实例中,如果要访问 data
上的数据,或者要访问 methods
中的方法, 必须带 ==this==
1.使用 v-cloak
能够解决 插值表达式闪烁的问题
2.默认 v-text
是没有闪烁问题的
3.v-text
会覆盖元素中原本的内容,但是 插值表达式 只会替换自己的这个占位符,不会把 整个元素的内容清空
Vue指令之v-text
和v-html
Vue指令之v-bind
的三种用法
========属性绑定机制========
-
直接使用指令
v-bind
-
使用简化指令
:
-
在绑定的时候,拼接绑定内容:
:title="btnTitle + ', 这是追加的内容'"
Vue指令之v-on
和跑马灯效果
Vue指令之v-on
========事件绑定机制========
-
直接使用指令
v-on
-
使用简化指令
@
跑马灯效果
- HTML结构:
复制代码{
{info}}
- Vue实例:
// 注意:在 VM实例中,如果想要获取 data 上的数据,或者 想要调用 methods 中的 方法,必须通过 this.数据属性名 或 this.方法名 来进行访问,这里的this,就表示 我们 new 出来的 VM 实例对象 // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { info: '猥琐发育,别浪~!', intervalId: null // 在data上定义 定时器Id }, methods: { go() { // 如果当前有定时器在运行,则直接return if (this.intervalId != null) { return; } // 开始定时器 this.intervalId = setInterval(() => { this.info = this.info.substring(1) + this.info.substring(0, 1); }, 500); // 注意: VM实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把 最新的数据,从data 上同步到页面中去;【好处:程序员只需要关心数据,不需要考虑如何重新渲染DOM页面】 }, stop() { clearInterval(this.intervalId); // 每当清除了定时器之后,需要重新把 intervalId 置为 null this.intervalId = null; } } }); // 分析: // 1. 给 【浪起来】 按钮,绑定一个点击事件 v-on @ // 2. 在按钮的事件处理函数中,写相关的业务逻辑代码:拿到 msg 字符串,然后 调用 字符串的 substring 来进行字符串的截取操作,把 第一个字符截取出来,放到最后一个位置即可; // 3. 为了实现点击下按钮,自动截取的功能,需要把 2 步骤中的代码,放到一个定时器中去;复制代码
Vue指令之v-on的缩写
和事件修饰符
事件修饰符:stop、prevent、capture、self、once
- .stop 阻止冒泡
复制代码
- .prevent 阻止默认事件
有问题,先去百度复制代码
- .capture 添加事件侦听器时使用事件捕获模式
复制代码
- .self 只当事件在该元素本身(比如不是子元素)触发时触发回调
复制代码
- .once 只触发一次事件处理函数
有问题,先去百度 复制代码
Vue指令之v-model
和双向数据绑定
Vue指令之v-model
1.v-bind
只能实现数据的单向绑定,从 M 自动绑定到 V, 无法实现数据的双向绑定
2.使用 v-model
指令,可以实现 表单元素和 Model 中数据的双向数据绑定
3.注意: v-model
只能运用在 ==表单==元素中
input(radio, text, address, email....) select checkbox textarea
简易计算器案例
- HTML 代码结构
复制代码
- Vue实例代码:
// 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { n1: 0, n2: 0, result: 0, opt: '0' }, methods: { getResult() { switch (this.opt) { case '0': this.result = parseInt(this.n1) + parseInt(this.n2); break; case '1': this.result = parseInt(this.n1) - parseInt(this.n2); break; case '2': this.result = parseInt(this.n1) * parseInt(this.n2); break; case '3': this.result = parseInt(this.n1) / parseInt(this.n2); break; } } } });复制代码
在Vue中使用样式
使用class样式
- 数组
这是一个邪恶的H1
复制代码
- 数组中使用三元表达式
这是一个邪恶的H1
复制代码
- 数组中嵌套对象
这是一个邪恶的H1
复制代码
- 直接使用对象
这是一个邪恶的H1
复制代码
使用内联样式
- 直接在元素上通过
:style
的形式,书写样式对象
这是一个善良的H1
复制代码
- 将样式对象,定义到
data
中,并直接引用到:style
中
- 在data上定义样式:
data: { h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }}复制代码
- 在元素中,通过属性绑定的形式,将样式对象应用到元素中:
这是一个善良的H1
复制代码
- 在
:style
中通过数组,引用多个data
上的样式对象
- 在data上定义样式:
data: { h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }, h1StyleObj2: { fontStyle: 'italic' }}复制代码
- 在元素中,通过属性绑定的形式,将样式对象应用到元素中:
这是一个善良的H1
复制代码
Vue指令之v-for
和key
属性
- 迭代数组
- 索引:{ {i}} --- 姓名:{ {item.name}} --- 年龄:{ {item.age}}
- 迭代对象中的属性
{ {val}} --- { {key}} --- { {i}}复制代码
- 迭代数字
==注意:如果使用 v-for 迭代数字的话,前面的 count 值从 1 开始==
这是第 {
{i}} 个P标签复制代码
2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的。==(只接受 string / number)==
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。
Vue指令之v-if
和v-show
-
v-if
的特点:每次都会重新删除或创建元素 -
v-show
的特点: 每次不会重新进行DOM的删除和创建操作,只是切换了元素的 display:none 样式 -
v-if 有较高的切换性能消耗
-
v-show 有较高的初始渲染消耗
-
如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show
-
如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if
一般来说,v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换 v-show 较好,如果在运行时条件不大可能改变 v-if 较好。
品牌管理案例
添加新品牌
add() { // 添加的方法 // console.log('ok') // 分析: // 1. 获取到 id 和 name ,直接从 data 上面获取 // 2. 组织出一个对象 // 3. 把这个对象,调用 数组的 相关方法,添加到 当前 data 上的 list 中 // 4. 注意:在Vue中,已经实现了数据的双向绑定,每当我们修改了 data 中的数据,Vue会默认监听到数据的改动,自动把最新的数据,应用到页面上; // 5. 当我们意识到上面的第四步的时候,就证明大家已经入门Vue了,我们更多的是在进行 VM中 Model 数据的操作,同时,在操作Model数据的时候,指定的业务逻辑操作; var car = { id: this.id, name: this.name, ctime: new Date() } this.list.push(car) this.id = this.name = '' }复制代码
删除品牌
del(id) { // 根据Id删除数据 // 分析: // 1. 如何根据Id,找到要删除这一项的索引 // 2. 如果找到索引了,直接调用 数组的 splice 方法 /* this.list.some((item, i) => { if (item.id == id) { this.list.splice(i, 1) // 在 数组的 some 方法中,如果 return true,就会立即终止这个数组的后续循环 return true; } }) */ var index = this.list.findIndex(item => { if (item.id == id) { return true; } }) // console.log(index) this.list.splice(index, 1) }, 复制代码
根据条件筛选品牌
- 1.x 版本中的filterBy指令,在2.x中已经被废除:
{ {item.id}} { {item.name}} { {item.ctime}} 删除 复制代码
- 在2.x版本中:
- 筛选框绑定到 VM 实例中的
searchName
属性:
输入筛选名称:复制代码
- 在使用
v-for
指令循环每一行数据的时候,不再直接item in list
,而是in
一个 过滤的methods 方法,同时,把过滤条件searchName
传递进去:
{ {item.id}} { {item.name}} { {item.ctime}} 删除 复制代码添加品牌
search
过滤方法中,使用 数组的filter
方法进行过滤:
// 注意: forEach some filter findIndex 这些都属于数组的新方法, // 都会对数组中的每一项,进行遍历,执行相关的操作;search(name) {//第一种方法/* var newList = [] this.list.forEach(item => { if (item.name.indexOf(keywords) != -1) { newList.push(item) } }) return newList */ //第二种方法 return this.list.filter(x => { return x.name.indexOf(name) != -1; // 注意 : ES6中,为字符串提供了一个新方法,叫做 String.prototype.includes('要包含的字符串') // 如果包含,则返回 true ,否则返回 false // contain /* if (item.name.includes(keywords)) { return item }*/ }); }复制代码
Vue调试工具vue-devtools
的安装步骤和使用
过滤器
概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示;
-
过滤器的定义语法
-
Vue.filter('过滤器的名称', function(){})
-
过滤器中的 function ,第一个参数,已经被规定死了,永远都是 过滤器 管道符前面 传递过来的数据
-
过滤器调用时候的格式
-
{
{ name | 过滤器的名称 }}
私有过滤器
- HTML元素:
{ {item.ctime | dataFormat('yyyy-mm-dd')}}复制代码
- 私有
filters
定义方式:
filters: { // 私有局部过滤器,只能在 当前 VM 对象所控制的 View 区域进行使用 dataFormat(input, pattern = "") { // 在参数列表中 通过 pattern="" 来指定形参默认值,防止报错 var dt = new Date(input); // 获取年月日 var y = dt.getFullYear(); var m = (dt.getMonth() + 1).toString().padStart(2, '0'); var d = dt.getDate().toString().padStart(2, '0'); // 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日 // 否则,就返回 年-月-日 时:分:秒 if (pattern.toLowerCase() === 'yyyy-mm-dd') { return `${y}-${m}-${d}`; } else { // 获取时分秒 var hh = dt.getHours().toString().padStart(2, '0'); var mm = dt.getMinutes().toString().padStart(2, '0'); var ss = dt.getSeconds().toString().padStart(2, '0'); return `${y}-${m}-${d} ${hh}:${mm}:${ss}`; } } }复制代码
==使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='') 或 String.prototype.padEnd(maxLength, fillString='')来填充字符串;==
全局过滤器
// 定义一个全局过滤器Vue.filter('dataFormat', function (input, pattern = '') { var dt = new Date(input); // 获取年月日 var y = dt.getFullYear(); var m = (dt.getMonth() + 1).toString().padStart(2, '0'); var d = dt.getDate().toString().padStart(2, '0'); // 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日 // 否则,就返回 年-月-日 时:分:秒 if (pattern.toLowerCase() === 'yyyy-mm-dd') { return `${y}-${m}-${d}`; } else { // 获取时分秒 var hh = dt.getHours().toString().padStart(2, '0'); var mm = dt.getMinutes().toString().padStart(2, '0'); var ss = dt.getSeconds().toString().padStart(2, '0'); return `${y}-${m}-${d} ${hh}:${mm}:${ss}`; }});复制代码
注意:当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!
键盘修饰符以及自定义键盘修饰符
1.x中自定义键盘修饰符【了解即可】
Vue.directive('on').keyCodes.f2 = 113;复制代码
- 通过
Vue.config.keyCodes.名称 = 按键值
来自定义案件修饰符的别名:
Vue.config.keyCodes.f2 = 113;复制代码
- 使用自定义的按键修饰符:
复制代码
- 自定义全局和局部的 自定义指令:
// 自定义全局指令 // 使用 Vue.directive() 定义全局的指令 v-focus // 其中:参数1 : 指令的名称,注意,在定义的时候,指令的名称前面,不需要加 v- 前缀, // 但是: 在调用的时候,必须 在指令名称前 加上 v- 前缀来进行调用 // 参数2: 是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作 Vue.directive('focus', { bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次 // 注意: 在每个 函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象 // 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用 // 因为,一个元素,只有插入DOM之后,才能获取焦点 // el.focus() }, inserted: function (el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】 el.focus() // 和JS行为有关的操作,最好在 inserted 中去执行,放置 JS行为不生效 }, updated: function (el) { // 当VNode更新的时候,会执行 updated, 可能会触发多次 } }) // 自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色 和 字体粗细: // 样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式 // 将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素 directives: { color: { // 为元素设置指定的字体颜色 bind(el, binding) { el.style.color = binding.value; } }, 'font-weight': function (el, binding2) { // 自定义指令的简写形式,等同于定义了 bind 和 update 两个钩子函数 el.style.fontWeight = binding2.value; } }复制代码
- 自定义指令的使用方式:
复制代码
Vue 1.x 中 自定义元素指令【已废弃,了解即可】
Vue.elementDirective('red-color', { bind: function () { this.el.style.color = 'red'; }});复制代码
使用方式:
1232 复制代码