本文共 10766 字,大约阅读时间需要 35 分钟。
vue是典型的mvvmm模式框架
M:模型层
v:视图层
vm:视图模型层
mvvm特点:数据双向绑定
一个方向是数据由模型进入视图 通过数据绑定实现的
一个方向是数据由视图进入模型 通过事件监听实现的
在vue中,实现了MVVM模式,
M:数据对象
V:视图模板
VM:vue实例化对象
通过new Vue方式创建vue实例化对象
通过el属性绑定视图模板
css选择器
通过data属性绑定数据模型
案列:
body>//引入vue{ {title}}
定义对象 存放空数据和备份空数据对象
通过ES5特性Object.defineProperty方法中get set方法对数据进行取值 赋值
get取值方法中不能通过自身属性取值 所有我们将对象中备份的数据 拿过来调用 返回备份的数据、
set 赋值方法中 也一样不能为自身属性赋值 我们可以通过备份的数据来存储对象 然后来更下视图
然后获取vue #app 获取视图模板
最后更新视图 用正则验证从data获取数据
更新视图 上树
// 数据let data = { title: '', // 备份数据 _data: {}}// 定义特性Object.defineProperty(data, 'title', { // 定义特性属性或者特性方法 // 取值方法 get() { // console.log('get') // 注意:不能通过自身属性取值 // return this.title // 返回备份的数据 return this._data.title; }, // 赋值方法 set(value) { // this指向对象 // 注意:不能为自身属性赋值 // this.title = value // 我们可以向备份数据中存储 this._data.title = value; // console.log('set') // 更新视图 updateView(this._data) }})// 视图模板let tpl = document.getElementById('app').innerHTML// 实现更新视图的方法function updateView(data) { // 处理模板 let html = tpl.replace(/{ {(\w+)}}/g, (match, $1) => { // 从data中获取数据 return data[$1] || '' }) // 更新视图 document.getElementById('app').innerHTML = html;}// 修改数据data.title = 'hello';
将ES6编译成ES5或者ES3.1的版本
webpack配置文件:webpack.config.js
我们使用commonjs模块化开发规范
在ES6中,我们使用ES Module模块化开发规范引入模块import 接口 from 模块import { 接口1, 接口2 } from 模块import * as 接口 from 模块暴露接口 引入单例接口实现expoetexport 接口通过后两种方式引入export default 接口 引入样式我们引入样式可以简写成import 样式地址
如果想省略拓展名的话,要在resolve的extensions配置中,定义文件的默认拓展名
vue入口文件
我们通过resolve中的alians为模块起别名
// commonjsmodule.exports = { // 解决问题 resolve: { // 拓展名 extensions: ['.es'], // 模块入口文件 alias: { vue$: 'vue/dist/vue.js' } }, // 入口 entry: { '03': './es/03.es', '04': './es/04.es', '05': './es/05.es', '06': './es/06.es', '07': './es/07.es', '08': './es/08.es', '09': './es/09.es', '10': './es/10.es', '11': './es/11.es', '12': './es/12.es', '13': './es/13.es' }, // 发布 output: { // 4.0要注意,不要加./dist // 4.0还要配置mode filename: './dist/[name].js' }, // 模块 module: { // 加载机 rules: [ // es6 { test: /\.es$/, loader: 'babel-loader', query: { presets: ['es2015'] } }, // css { test: /\.css$/, loader: 'style-loader!css-loader' }, // less { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // scss { test: /\.scss$/, loader: 'style-loader!css-loader!sass-loader' } ] }}
vue实现了数据绑定:模型中的数据改变,视图同步更新。
如果数据改变了,而视图没有更新,那么我们就说数据丢失了。
vue中数据绑定是通过ES5中属性特性实现的,因此没有绑定特性的属性,就会丢失数据。
数据丢失是框架的Bug
常见的数据丢失有四类
第一类:数组中的值类型数据。
解决:用新数组覆盖原来的数组
第二类:数组中的新成员。
解决:用新数组覆盖原来的数组
第三类:对象中的新属性。
解决:用新对象覆盖原来的对象。
第四类:未在模型中声明的数据。
声明这类数据
作者为了解决数据丢失问题,提供了一个辅助方法:$set
$set(target, key, value)
target 目标对象,可以是vue实例化对象
key 属性名称
vlaue 属性值
// 引入import Vue from 'vue';// 实例化let app =new Vue({ // 容器 el:'#app', data:{ title:'你好', // 数组 // 如果你带入的东西里面有加入附带的属性值这时候你就要在数组后加入属性值要不然数据就会丢 // 数组的值与插值中的值要相同 colors: ['red', 'green', 'blue','yellow','skyblue'], // 这里设置对象中的新属性 obj:{ width:10, height:20 }, // 初始化 abc:'' }})app.colors[1]='orange' //出现数据丢失 // 1:新数组 用新数组覆盖原来的数组app.colors=['orange','green','blue','yellow','skyblue']// 作者为了解决数据丢失问题,提供了一个辅助方法:$set// $set(target, key, value)// target 目标对象,可以是vue实例化对象// key 属性名称// vlaue 属性值// 这里使用的就是解决数据丢失的问题// app.$set(app.colors, '0', 'purple') //'purple','green','blue','yellow','skyblue'// 2:通过填加新的数组来防止数据丢失app.colors[7]='yellow' //出现数据丢失// 新数组替换// app.colors = ['red', 'green', 'blue','yellow','skyblue', ,'yellow']// 3:对象中的新属性app.obj.size = 200 //数据丢失 // 新对象替换 这里需要替换新数据那么前面插值的属性值也需要被需改app.obj={ width: 10, height: 40, size: 200}// 4 为初始化数据 修改初始化的属性名 //没在初始化中设置属性名 数据丢失app.abc = 'efg';{ {colors[0]}}---{ {colors[1]}}---{ {colors[2]}}--{ {colors[3]}}
{ {colors[0]}}---{ {colors[1]}}---{ {colors[5]}}
{ {obj.width}}---{ {obj.size}}
{ {abc}} 123
使用插值的目的是为了将模型中的数据渲染到页面中(视图中)
小程序中的插值语法提供了伪js环境。
vue中的插值提供了真正的js环境,因此我们可以直接使用js表达式
在2.0中,不允许我们对属性插值。
想动态的设置元素的属性值,我们可以使用v-bind指令。
指令:指令就是对元素的拓展,使其具有一定的行为特征(功能)
v-bind实现的功能:动态的设置元素属性值。
v-bind指令的语法糖是:语法糖
语法糖:语法糖就是对某个操作的简化,来提高我们的开发效率
我们可以用:语法糖来简化v-bind指令
v-bind:key=”value”
:key=”value”
注意:在vue中,所有的指令的属性值都是js环境
// 引入import Vue from 'vue';// 实例化let app=new Vue({ // 容器 el:'#app', data:{ title:'hello' }})前端
前端
前端
作用:设置元素的内容。
与插值语法相比:
1 避免插值符号闪烁
2 插值语法可以设置一部分内容,v-text指令设置元素全部内容
注意:v-text与插值语法一样,都不能渲染html标签。
作用:设置元素的内容,并可以渲染html标签
可以避免插值符号闪烁,并且设置元素的全部内容
注意:在工作中,渲染的内容一定要可靠
作用:让渲染的内容渲染一次
当数据更新的时候,该元素不会再次更新了
该指令对于元素的后代元素仍然生效
该指令不需要属性值,但是在该元素(包括子元素)中的指令,如:v-text,v-html,v-bind,插值。都只会渲染一次
在2.0中,使用过滤器的语法
{
{ data | filter(arg1, arg2) | filter2 }}当使用多个过滤器的时候,前一个过滤器的输出将作为后一个过滤器的输入
vue提供了filter方法,可以自定义过滤器
第一个参数表示过滤器名称
第二个参数表示过滤函数
第一个参数表示处理的数据
从第二个参数开始,表示传递的参数
必须有返回值,就是过滤的结果
注意:
filter方法,有vue提供,但是不能解构
在vue实例化之前,定义过滤器
// 过滤器不能解构import Vue from 'vue';// 语义化// componentWillReceiveProps// dangerouslySetInnerHTML// 定义过滤器Vue.filter('tocamel', (str, firstCharIsUpper, ...arg) => { // console.log(arg) // 如果首字母大写 if (firstCharIsUpper) { // slice, substring, substr str = str[0].toUpperCase() + str.slice(1) } // 正则中的表达 // () [] {} ^ $ ? * + . \ // return str.replace(/[-_]([a-z])?/g, (match, $1 = '') => { // // 将$1大写 // return $1.toUpperCase() // }) // 省略 return str.replace(/[-_]([a-z])?/g, (match, $1 = '') => $1.toUpperCase());})// 实例化let app = new Vue({ // 容器 el: '#app', // 数据 data: { msg: 'abc_efg-hij_klm-Nop' } }){ {msg | tocamel}}
事件修饰符
stop 阻止冒泡
prevent 取消默认行为
self 触发事件的元素与绑定事件的元素是同一个元素
once 单次触发。
为了检测点击的鼠标按键,vue提供了鼠标修饰符。
left 点击左键
right 点击右键
middle 点击中间件
vue为系统组合键提供了修饰符
shilft, ctrl, alt, meta
我们可以通过修饰符,使用这些组合键
在点击该按键的时候,再触发事件。
当我们绑定键盘事件的时候(keydown,keyup,keypress),我们可以添加键盘事件修饰符,来快速的捕获某个键。
在过去,我们要获取事件对象,判断e.keyCode。
键盘事件修饰符包括:esc, tab, space, enter, delete, up, down, left, right, 以及所有字母。
为了动态的为元素添加类,我们可以通过v-bind指令,动态绑定类,有三种绑定方式
第一种 :class=”{}”
key 表示一组类的名称(包含空格)
value 是否保留这组类
true 保留类
false 删除类
第二种 :class=”[]”
每一个成员代表一组类(包含空格)
第三种 :class=”str”
代表一组类(包含空格)
我们可以使用字符串拼接形式。
.blog { font-size: 12px; span { // display: inline-block; padding: 15px 20px; background: #efefef; } ul { border-left: 1px solid orange; border-right: 1px solid orange; background: #fff; padding-left: 0; width: 100px; display: none; li { border-bottom: 1px solid orange; list-style: none; line-height: 30px; padding-left: 10px; } } &.show ul { display: block; }}// 引入vueimport Vue from 'vue';// 引入样式import './demo.scss';// 实例化new Vue({ // 容器 el: '#app', // 数据 data: { color: 'bg-orange', cls: '' }, // 方法 methods: { // 显示博客 showBlog() { // 添加类 this.cls = 'show'; }, // 隐藏博客 hideBlog() { // 删除类 this.cls = ''; } }})博客
- 博客评论
- 未读提醒
.goods { width: 400px; margin: 50px auto; p { line-height: 40px; } label { font-size: 14px; margin-right: 50px; } span { border: 1px solid #ccc; font-size: 12px; display: inline-block; text-align: center; height: 40px; line-height: 40px; width: 40px; margin-right: 10px; cursor: pointer; } img { vertical-align: middle; border: 1px solid #ccc; margin-right: 10px; &.disabled { cursor: not-allowed; border-style: dashed; } }}// 引入vueimport Vue from 'vue';// 引入样式import './demo.scss';// 实例化new Vue({ // 容器 el: '#app', // 数据 data: { color: 'red', span: [], img: [] }, // 方法 methods: { // 切换尺码 choose(num) { // 判断 switch (num) { // 判断 case 37: // this.span[0] = 'red' // 解决数据丢失 // this.$set(this.span, 0, 'red') // 为了避免数据丢失,并且不遗漏数据,我们要赋值数组 this.span = ['red'] this.img = ['disabled', 'disabled', 'disabled'] break; case 38: // this.span[1] = 'red' // 不能修改一个成员,其它的数据改动会遗漏 // this.$set(this.span, 1, 'red') // this.$set(this, 'span', [, 'red']) this.span = [, 'red'] this.img = ['disabled', 'disabled'] break; case 39: // this.span[2] = 'red' // this.$set(this.span, 2, 'red') this.span = [, , 'red'] this.img = [] break; } // console.log(this) } }})37 38 39
通过v-if来定义。控制元素是否创建。
属性值是true 创建该元素
属性值是false 删除该元素
是真正的创建和删除,不是显示和隐藏
与v-if相关的组合指令有:v-else, v-else-if
通过v-show指令,控制元素的显示和隐藏,
不是模板指令,没有删除或者创建元素。
实现原理:通过切换样式:display: none实现的。
与v-if的区别1 实现原理
v-if:创建和删除元素
v-show:显示和隐藏元素,没有创建或者删除元素。
2 组合指令
v-if可以与v-else以及v-else-if一起使用
v-show不能
注意:由于显隐指令v-show性能更高,所以工作中更常用。
vue模仿for in循环,提供了循环模板指令。
循环模板指令有两种语法。
v-for=”item in data”
v-for=”(item, index) in data”
in 表示关键字
item 表示成员值
index 表示索引值
data 表示在vue中定义的数据,有三类数据:
第一类,data是数组。
item表示成员值
index表示索引值
第二类,data是对象,
item表示属性值 value
index表示属性名称 key
第三类,data是数字,表示循环data次
item从1计数
index从0计数
注意:在v-for循环中,我们要为元素设置key属性,并且属性值是唯一的。
我们通常可以设置索引值(index)或者数据的唯一属性,如id。
后面我们使用vue cli的时候,不设置key会抛出错误
// 引入vueimport Vue from 'vue';// 引入样式import './demo.scss';// 实例化new Vue({ // 容器 el: '#app', // 数据 data: { news: ["\"香港乱了 北京该不该强力出手\"热点", "\"只要我想 美军10天就消灭阿富汗\"国际", "霍顿被国际泳联警告 还被揭黑历史体育", "麦当劳外卖价比堂食贵11元被质疑 消费", "山西为何被一个安徽城市吓了一跳国内", "富豪半年花386亿买下2110套别墅"], num: 10, obj: { color: 'red', title: 'hello', width: 100 } },})
- { {item}}--{ {index}}
我们可以通过v-show指令,显示或者隐藏元素
我们还可以通过v-if指令,创建或者删除元素,
vue允许我们在显示与隐藏,或者创建与删除过程中,添加动画
这里的动画是通过css3实现的,因此要定义样式。
我们通过transition元素(组件)为内部的元素添加过渡动画。
通过name定义过渡动画类的名称
例如 name=”ickt”,此时在显示与隐藏,或者创建与删除过程中会出现六个类
显示过程中:.ickt-enter, .ickt-enter-to, .ickt-enter-active
隐藏过程中:.ickt-leave, .ickt-leave-to, .ickt-leave-active
注意:
显示过程中:类包含enter
元素由隐藏的状态变成显示的状态
隐藏过程中:类包含leave
元素由显示的状态变成隐藏的状态
我们可以基于这些类,为元素添加过度动画
在js中,监听css动画可以通过事件:
webkitTransitionStart, webkitTransitionEnd
webkitAnimationStart, webkitAnimationEnd
vue允许我们为transtion绑定事件,监听动画。
显示过程中
before-enter 显示动画开始
enter 显示动画进行中
after-enter 显示动画结束
隐藏过程中
before-leave 隐藏动画开始
leave 隐藏动画进行中
after-leave 隐藏动画结束
我们通过@语法糖绑定这些事件。
转载地址:http://goven.baihongyu.com/