vue2基础教程

vue特性与其他框架的区别

关于vue

  • vue是一个简洁且轻量化为主要特点的前端MVVM开发框架,vue使用组件化开发的范式,组件之间可以做到高度解耦,数据的绑定、更新、动态界面等特性也一气呵成。

特性

  • 轻量----很小并不依赖其他基础库
  • 数据绑定----MVVM
  • 指令----指令控制DOM
  • 插件化----vue-resourse、vue-cli等

vue与其他框架的区别

对比angular

  • 都支持指令,支持过滤器,支持双向绑定,都不支持低端浏览器
  • angular学习成本高,性能上,依赖对数据做脏检查,watcher越多越慢。

对比react

  • react采用特殊的jsx语法,vue推崇编写.vue特殊的文件格式,都需要编译后使用
  • 中心思想都是 组件,组件实例之间可以嵌套
  • 都支持生命周期函数
  • recat依赖虚拟DOM,vue使用的是DOM模板
  • react采用的虚拟DOM会对渲染出来的结果进行脏检查, vue采用的是数据劫持,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

vue实例

image.png

先上代码:

<div id="app">//id
    {{ message }}//接受js表达式的值(ps:js语句是一种行为,不会产生值;js表达式会产生一个值)
</div>
<script>
  var app = new Vue({//new一个实例
        el: '#app',//连接DOM
        data: {
            message: 'Hello Vue!'//初始数据
        }
  })
</script>
关于构造器
  • 每个vue.js都是通过构造函数vue创建 一个vue的根实例启动的
  • (在实例化vue时,需要传入一个选项对象,他可以包括数据、模板、挂载元素、方法、生命周期钩子等选项。)
var vm = new Vue({
      // 选项(数据、模板、挂载元素、方法、生命周期等)
})
  • 可以扩展vue构造器,从而预定选项创建可复用的组件构造器(后期详细解释)
var MyComponent=Vue.extend({
          //扩展选项
})
//所有的MyComponent 实例都将以预定义的扩展选项被创建
var MyComponent=new MyComponent();
//所有的 Vue.js 组件其实都是被扩展的 Vue 实例。
构造器属性与方法
  • 每个vue实例都会代理其data对象里的所有的属性
var data={a:1}
var vm=new Vue({
     data:data
})
vm.a===data.a      //true
//设置属性也会影响到原始数据
vm.a=2;
console.log(data.a);      //2
  • 除了 data 属性, Vue 实例暴露了一些有用的实例属性与方法。这些属性与方法都有前缀 $:
  1. vm.$data===data ---//true vm上的数据
  2. vm.$el===document.getElementById('example')---// 当前的el元素
  3. vm.set ---后加的属性实现响应式变化(因为如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。) eg: vm.set(data,'sex', '男');
  4. vm.$options ---//vm上的所有的属性
  5. vm.$nextTick(()=>{console.log(vm)})---//异步方法,等待dom完成后可以操作dom,(每次数据改变之后想 要获取操作DOM,都可以使用nextTick)。
  6. vm.$watch---是一个实例方法 监听函数
  7. vm.$refs ---//关联ref属性的DOM元素,可以操作这个关联的元素
<div id='example'>
  <p ref='mydom'>{{msg}}</p>  
  <p ref='mydom'>{{msg}}</p>
  <div ref='mydiv' v-for="a in arr">{{a}}</div >
</div>
........
var data={msg:1,arr:[1,2,3]}
    var vm=new Vue({
        el:'#example',
        data:data,
        mounted(){
          //如果dom元素不是通过v-for循环出来的,只能获取一个,通过-for循环出来的可以获取多个
          console.log(this.$refs.mydom)//获取一个p
          console.log(this.$refs.mydiv)//获取多个div
        }
    })
     vm.$data===data    ---//true  vm上的数据
     vm.$el===document.getElementById('example')---// 当前的el元素
     vm.$set ---后加的属性实现响应式变化(因为如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。) eg: vm.$set(data,'sex', '男');
     vm.$options  ---//vm上的所有的属性
     vm.$nextTick(()=>{console.log(vm)})---//异步方法,等待dom完成后可以操作dom,(每次数据改变之后想 要获取操作DOM,都可以使用nextTick)。
     vm.$watch---是一个实例方法 监听函数
     vm.$refs   ---//关联ref属性的DOM元素,可以操作这个关联的元素
  • $watch是一个实例方法 监听函数
vm.$watch('a',function(newVal,oldVal){
        //这个回调会在`vm.a`改变后调用
    })

注:不要在实例属性或者回调函数中(如 vm.$watch('a', newVal => this.myMethod()))使用箭头函数。因为箭头函数绑定父上下文,所以 this 不会像预想的一样是 Vue 实例,而是 this.myMethod 未被定义。

vue模板

文本 : {{}}---Mustache” 语法

数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值
<span>Message: {{ msg }}</span>
绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。
<span v-once> v-once属性会让元素里边的值永远不会改变{{ msg }}</span>

纯html : v-html='数据'

双大括号会将数据解释为纯文本,而非 HTML 。为了输出真正的 HTML ,你需要使用 v-html 指令
<div v-html="rawHtml"></div>
被插入的内容都会被当做 HTML —— 数据绑定会被忽略

属性 : v-bind:propName='数据'

Mustache 不能在 HTML 属性中使用,应使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>

数据可以使用js表达式加工生成

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>

vue指令

是带有v-前缀的特殊属性。指令属性的值预期是单一js表达式。
指令的职责就是当其表达式的值改变时相应的将某些行为应用到DOM上。

参数:
一些指令能接受一个参数 在指令后以冒号指明,例如,v-bind指令被用来响应的更新HTML的属性:

<a v-bind:href='url'></a>
<a v-on:click="doSomething">

修饰符
修饰符是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如:prevent,stop,capture,self,once,

.prevent修饰符告诉v-on指令对于触发事件调用 event.preventDefault();
<form v-on:submit.prevent='onSubmit'>

v-if 显示隐藏

<div id="app-3">
    <p v-if="seen">现在你看到我了1</p>
    <p v-else>现在你看到我了2</p>
</div>
var app3 = new Vue({
        el: '#app-3',
        data: {
            seen: true
        }
    })

template标签的使用


image.png

v-show (状态一直改变性能强于v-if)

<div id="app-3">
    <p v-show="seen">现在你看到我了</p>
</div>
var app3 = new Vue({
        el: '#app-3',
        data: {
            seen: true
        }
    })

v-for 循环

<div id="app-4">
    <ol>
        <li v-for="todo in todos">
            {{ todo.text }}  //渲染每一个text 
        </li>
    </ol>
</div>
var app4 = new Vue({
        el: '#app-4',
        data: {
            todos: [
                { text: '学习 JavaScript' },
                { text: '学习 Vue' },
                { text: '整个牛项目' }
            ]
        }
    })

v-model:双向绑定

<div id="app-3">
    <p>{{ text}}</p>
    <input v-model="text">
</div>
var app3 = new Vue({
        el: '#app-3',
        data: {
            text: 'hello'
        }
    })

v-text='data' 相当于 {{data}}

v-html 相当于可以渲染DOM的 v-text

v-bind 绑定属性(可缩写为 :属性名=' data ')

<div id="app-2">
  <span v-bind:title="message">//添加title属性(<span :title="message">)
    鼠标悬停几秒钟查看此处动态绑定的提示信息!
  </span>
</div>
var app2 = new Vue({
        el: '#app-2',
        data: {
            message: '页面加载于 ' + new Date()
        }
    })

v-on绑定事件(可缩写为 @事件名=" 函数名 ")

<div id="app-5">
    <p>{{ message }}</p>
    <button v-on:click="reverseMessage">逆转消息</button>
    //缩写为 <button @click="reverseMessage">逆转消息</button>
</div>
var app5 = new Vue({
        el: '#app-5',
        data: {
            message: 'Hello Vue.js!'
        },
        methods: {
            reverseMessage: function () {
                this.message = this.message.split('').reverse().join('')
            }
        }
    })

计算属性computed

先贴个示例

<div id="demo">{{ fullName }}</div>
//js代码
<script>
var vm = new Vue({
            el: '#demo',
            data: {
                firstName: 'Foo',
                lastName: 'Bar'
            },
            computed: {
                fullName: function () {
                    return this.firstName + ' ' + this.lastName
                }
            }
        })
</script>

计算属性的缓存 和 methods的比较

  • 计算属性只有在它的相关依赖发生改变时才会重新求值(有缓存),相比methods节约了性能。
  • 这就意味着只要 firstName,lastName还没有发生改变,多次访问 fullName计算属性会立即返回之前的计算结果,而不必再次执行函数。

计算属性 和 Watched属性的比较

  • 当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch。
  • 通常更好的想法是使用 computed 属性而不是命令式的 watch 回调。

计算属性默认只拥有getter方法,但是可以自定义一个setter方法。

computed: {(最大的特点:不支持异步,如果需要异步执行要用watch)
        fullName: {
          // getter  监听获取的回调
          get: function () {
            return this.firstName + ' ' + this.lastName
          },
          // setter  监听设置的回调(给别人赋值,自身没有效果,所以一般不用set函数)
          set: function (newValue) {
            var names = newValue.split(' ')
            this.firstName = names[0]
            this.lastName = names[names.length - 1]
          }
        }
      }

观察者属性watch(数据不变不触发,能异步,但是性能不及computed,一次只能监听一个数据的变动)

通过watch属性可以手动观察Vue实例上的数据变动,当然也可以调用实例上的vm.$watch达到相同的目的。
使用watch属性的灵活性在于,当监测到数据变化的时候,可以做一些设置中间状态之类的过渡处理。

var watchExampleVM = new Vue({
    el: "#watch-example",
    data: {
      question: "",
      answer: "I cannot give you an answer until you ask a question!"
    },
    watch: {
      // 如果question发生改变,该函数就会运行
      question: function (newQuestion) {
        this.answer = "Waiting for you to stop typing..."
        this.getAnswer()
      }
    },
})

watch只能监控对象的一层数据,不能深层监控

解决办法

watch:{
  data:{//深度监控的数据
    handler(){//默认写成函数,就相当于默认写了个handler

    },deep:true
  }
}

过滤器(vue2.0已经把过滤器删除需要自己实现)

实现方法:https://blog.csdn.net/dream_broken/article/details/73481046

过滤器可以放在两个地方:mustache 插值和 v-bind 表达式。

    <!-- in mustaches -->
    {{ message | capitalize }}
    <!-- in v-bind -->
    <div v-bind:id="rawId | formatId"></div>

内置过滤器

  • capitalize用于将表达式中首字母转换为大写形式
{{'name'|capitalize}}--->'Name'
  • uppercase将表达式中所有的字母转换为大写形式
{{'name'|uppercase}}--->'NAME'
  • lowercase将表达式中所有的字母转换为小写形式
{{'NAME'|lowercase}}--->'name'
  • json 相当于JSON.stringify 后边可以跟一个数字,表示json字符串首行缩进的个数
data:
  obj:{name:'aa',age:'bb'}
{{obj|json 4}}
//输出
{    'name':    'aa',    'age':    'bb'}

*limitBy 限制数组为开始的前N个元素

//只显示开始的前10个元素
<div v-for='item in items | limitBy 10'></div>
//只显示第5到15个元素
<div v-for='item in items | limitBy 10  5'></div>
  • filterBy
//只显示包含hello字符串的item
<div v-for='item in items | filterBy "hello" '></div>
  • orderBy返回排序后的数组 >0为升序 <0为降序
//升序排列
<div v-for='item in items | orderBy order>0'></div>
  • currency过滤器 : 将输入的数字转换成现金的过滤器。可以跟上货币符号(默认$)和保留的小数位(默认2)。
<li v-for="product in products">
      {{ product.name | capitalize }} - {{ product.price | currency }}
</li>

自定义过滤器

  • 定义一个全局的自定义过滤器,需要使用Vue.filter()构造器。这个构造器需要两个参数。
Vue.filter() 
1.filterId: 过滤器ID,用来做为你的过滤器的唯一标识;
2.filter function: 过滤器函数,用一个function来接收一个参数,
之后再将接收到的参数格式化为想要的数据结果。

定义一个filter

Vue.filter( 'discount' , function(value,discount) {
        return value  * ( discount / 100 ) ;
  });

使用

<ul>
      <li v-for="product in products">
           {{ product.name | capitalize }} - {{ product.price | discount 25 | currency }}
      </li>
</ul>

或者

let vm=new Vue({
  el:'#app',
  filters:{//自定义过滤器
    toFixed(input,param1){//这里的this指向window
      return input.toFixed(param1);//input代表的是管道符‘|’前面的内容,param1代表的是toFixed中传递的参数
    }
  }
})

使用还是用竖线
{{ product.price| toFixed(2)}}//保留两位小数


关于样式操作

class

对象语法
  • 我们可以传给 v-bind:class 一个对象,以动态地切换 class:
<div v-bind:class="{ active: isActive }"></div>
  • v-bind:class 指令也可以与普通的 class 属性共存
<div class="static"
     v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>

data:

data: {
  isActive: true,
  hasError: false
}

结果渲染为:

<div class="static active"></div>

当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"。

  • 绑定的数据对象不必内联定义在模板里:
<div v-bind:class="classObject"></div>
data: {
  classObject: {
    active: true,
    'text-danger': false
  }
}
数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

渲染为

<div class="active text-danger"></div>

用三元表达式:

<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>

style

对象语法
div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
}

直接绑定到一个样式对象

<div v-bind:style="styleObject"></div>
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}

同样的,对象语法常常结合返回对象的计算属性使用。

数组语法

v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上

<div v-bind:style="[baseStyles, overridingStyles]"></div>
data: {
 baseStyles: {
   color: 'red',
   fontSize: '13px'
 },
 overridingStyles:{
   background:'#ccc',
 }
}

自动添加前缀
v-bind:style 使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀。

事件

一般写法---------------- v-on:click=function

简写------------------- @click=''

事件对象------------------ @click=show($event);

事件冒泡阻止冒泡 -----------1)ev.cancelBubble=true;=2)@click.stop 推荐

默认行为-----------阻止默认行为1)ev.preventDefault() 2)@contextmenu.prevent 推荐

键盘类的事件

@keydown $event  ev.keyCode
回车
@keyup.enter
@keyup.13
上下左右
@keyup/keydown.left/right/up/down

method配置

注意事项

  • methods重定义的this始终指向Vue实例
  • 与事件绑定的方法支持参数event即原生DOM事件的传入
  • 方法用在普通元素上,只能监听原生DOM事件,用在自定义元素组件上,也可以监听子组件触发的自定义事件

$event的使用

<button @click='say("hello",$event)'>submit</button>
method:{
  say:function(msg,event){
    console.log(msg);
    event.preventDefault();
  }

}

修饰符

  • 阻止默认行为prevent
<button @submit.prevent='submit("hello",$event)'>submit</button>
  • 阻止事件冒泡stop
<button @submit.stop='submit("hello",$event)'>submit</button>
  • 捕获模式capture
<button @submit.capture='submit("hello",$event)'>submit</button>
  • 事件只在该元素本身触发时执行self
<button @submit.self='submit("hello",$event)'>submit</button>
  • 事件的修饰符可以串联使用
<button @click.stop.prevent='doSomething'>submit</button>
  • 键盘事件
<input @keyup.enter='submit'>//enter事件
<input @keyup.tap='submit'>//tap事件
<input @keyup.up='submit'>//向上up事件
<input @keyup.delete='submit'>//delete事件
<input @keyup.space='submit'>//space空格事件

可参考文章:
https://www.jianshu.com/p/7f86d0e744be?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容