Vue入门实例及思想(一)
Vue是什么?
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
作者
尤雨溪/中国无锡,2014年正式发布,版本号0.8.0。
什么是渐进式?
我的理解为:一种由下到上的框架设计模式,Vue的核心部分只关心日常中最普遍的应用,而一些复杂的内容则采用组件的形式基于核心部分进行扩展,这看起来像是由浅到深。
Vue的环境
非常简单的引入你下载的Vue.js文件或者利用第三方的资源加速通道cdn,就可以在你的项目中使用它所带来的便捷了。
(1)下载地址:https://cn.vuejs.org/js/vue.js ,直接引入script标签:
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
(2)引用cdn(内容分发网络),有很多免费的cdn加速通道,这里采用bootstrap官方的cdn:
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
MVVM框架
MVVM是Model-View-ViewModel的简写本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。 来自百度百科介绍,MVVM就是标准的数据驱动开发模式,而Vue虽然没有完全遵循MVVM模型,但是 Vue 的设计也受到了它的启发。
通过以上图例可以看出,VM层才是Vue主要关注的部分(视图模型),VM层作为桥梁连接View视图层和Model模型层,Vue的设计就是当模型层的数据发生改变时视图层也动态的做出相应的改变,同样的在视图上的值发生改变时模型层也作出相应改变,实现数据的双向绑定,为我们省略了繁琐的开发步骤。
Vue生命周期
下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
入门实例
话不多说直接代码,代码是可以直接运行的。
<html> <head> <meta charset="utf-8" /> <title></title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js" type="text/javascript" charset="utf-8"></script> </head> <body> <!-- 指定vue管理内容区域,通常我们也把它叫做边界,这意味着我们接下来的改动全部在指定的div内,div外部不受影响 --> <div id="app"> {{ message }} {{ time }}<br /> <button v-on:click="domethod">想变身你就摸这里</button><br /> <input type="text" v-model="num" placeholder="输入数字" /><button v-on:click="doIncrement">+1</button><br /> <form v-on:submit.print> <!-- 1.核心思想MVVM数据双向绑定。 2.实例一:数据的改变引起DOM的改变,DOM的改变也会引起数据的变化。 3.实例二:只有当实例被创建的时候data中存在的属性才是响应式的。 4.实例三:Vue的实例关于从浏览器加载到数据加载的生命周期钩子函数 --> <input type="text" v-model="id" placeholder="输入账号" /><span>双向绑定:{{id}}</span><br /> <input type="text" v-model="password" placeholder="输入密码" /><br /> <input type="text" v-model="tel" placeholder="输入电话" /> <input type="button" value="提交" v-on:click="dosubmit()" /> </form> </div> <script type="text/javascript"> var app = new Vue({ //vue实例,与Vue相关的部分都从Vue的实例开始。 el: '#app', //vue的管理区域,也叫做边界或挂载区域 data: function() { //自定义组件中必须使用函数的方式返回vue属性 return { //定义vue的属性并且初始化。 message: 'Hello Vue!', time: new Date().getTime(), id: '', password: '', tel: '', num: '' } }, methods: { //定义函数用于事件的触发,绑定事件函数 domethod: function() { alert("你好啊,Vue的作者尤雨溪!"); //外部访问方式 console.log(app.message); //内部访问方式 console.log(this.message); }, dosubmit: function() { console.log("id:" + this.id); console.log("password:" + this.password); console.log("tel:" + this.tel); console.log('time:' + this.time);//获取到值就可以进行Ajax请求 this.id = "Vue的数据改变了!"; //数据的改变引起DOM的改变 }, doIncrement: function() { if(isNaN(this.num)==false){//是数字 this.num = parseInt(this.num) + 1; console.log(this.num); }else{//非数字 this.num = this.num.split('').reverse().join(''); } } }, beforeCreate:function(){ console.log('beforeCreate:刚刚new Vue()之后,这个时候,数据还没有挂载呢,只是一个空壳') console.log(this.message)//undefined }, created:function(){ console.log('created:这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数') this.message+='!!!' console.log('在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取') console.log('接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染') }, beforeMount:function(){ console.log('beforeMount:虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated') this.message+='@@@' console.log('在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取') console.log(document.getElementsByClassName("myp")[0])//undefined console.log('接下来开始render,渲染出真实dom') }, // render:function(createElement){ // console.log('render') // return createElement('div','hahaha') // }, mounted:function(){ console.log('mounted:此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了'); console.log('可以在这里操作真实dom等事情...'); console.log(this.message);//有数据 // this.$options.timer = setInterval(function () { // console.log('setInterval') // this.msg+='!' // }.bind(this),500) }, beforeUpdate:function(){ //这里不能更改数据,否则会陷入死循环 console.log('beforeUpdate:重新渲染之前触发') console.log('然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染') }, updated:function(){ //这里不能更改数据,否则会陷入死循环 console.log('updated:数据已经更改完成,dom也重新render完成') }, beforeDestroy:function(){ console.log('beforeDestory:销毁前执行($destroy方法被调用的时候就会执行),一般在这里善后:清除计时器、清除非指令绑定的事件等等...') // clearInterval(this.$options.timer) }, destroyed:function(){ console.log('destroyed:组件的数据绑定、监听...都去掉了,只剩下dom空壳,这里也可以善后') } }); </script> </body> </html>
相关语法实例
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script> <!-- 一个日期格式化的简单脚本 --> <script src="js/date.js" type="text/javascript" charset="utf-8"></script> <style type="text/css"> .test { background-color: aqua; font-size: 25px; } h2 { color: coral; } </style> </head> <body> <div id="app"> {{ts}} <h2>1.插值</h2> <h3>1.1文本</h3> <p>{{title}}</p> <h3>1.2html</h3> <p v-html="sss">{{sss}}</p> <h3>1.3v-bind插入值</h3> <div v-bind:style="binds">遇事不决可问春风</div> <div v-bind:id="id" style="color: brown;"></div> <h3>1.4表达式</h3> {{substrs.substr(0,6).toUpperCase()}}<br /> {{ number + 1 }}<br /> {{ ok ? 'YES' : 'NO' }}<br /> <li v-bind:id="'list-' + id">我的Id是js动态生成的</li> <h2>2.指令</h2> <h3>2.1 v-if、v-else-if、v-else</h3> <div> <div v-if="sex==='男'">是男人</div> <div v-else-if="sex==='女'">是女人</div> <div v-else>是人妖</div> </div> <h3>2.2 v-show</h3> <input type="checkbox" v-model="flag" />显示/隐藏 <div v-show="flag">人的内心,既求生,也求死。</div> <h3>2.3 v-for</h3> <li v-for="item in items">{{item.id}}{{item.name}}</li> <li v-for="(item,index) in items">{{index}}: {{item.id}}{{item.name}}</li> <li v-for="(key,value) in items">{{key}}{{value}}</li> <h3>2.4 v-bind</h3> <div v-bind:class="tes">既追求光明,也追求黑暗</div> <h3>2.5 v-on</h3> <button v-on:click="domethod">摸这里</button> <h3>2.6 v-model</h3> <!-- 多选框 --> <div v-for="it in items"> <input type="checkbox" v-model="checks" :value="it.id" />{{it.name}} </div> <div>{{checks}}</div> <!-- 单选框 --> <div v-for="it in items"> <input type="radio" v-model="radio" :value="it.id" />{{it.name}} </div> <div>{{radio}}</div> <h2>3.参数( 一些指令能够接收一个“参数”,在指令名称之后以冒号表示)</h2> <h3>3.1 v-bind</h3> <a v-bind:href="hrefs">百度</a> <h3>3.2 v-on</h3> <a href="javascript:void(0);" v-on:click="goBaidu">百度</a> <h2>4.动态参数(从2.6.0开始,可以用方括号括起来的JavaScript表达式作为一个指令的参数)</h2> <a v-bind:[attr]="hrefs">百度</a> <h3>4.1同样地,你可以使用动态参数为一个动态的事件名绑定处理函数</h3> <a href="javascript:void(0);" v-on:[evname]="domethod">摸这里</a> <h2>5.修饰符( 修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。)</h2> <h4>详见源码</h4> <!-- 阻止单击事件继续传播 --> <a v-on:click.stop="domethod"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="domethod"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="domethod"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件监听器时使用事件捕获模式 --> <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 --> <div v-on:click.capture="domethod">...</div> <!-- 只当在 event.target 是当前元素自身时触发处理函数 --> <!-- 即事件不是从内部元素触发的 --> <div v-on:click.self="domethod">...</div> <h2>6.简写(v- 前缀作为一种视觉提示,用来识别模板中 Vue 特定的 attribute,但这变得繁琐,所以Vue可以用简写替代前缀)</h2> <a v-bind:href="hrefs">百度</a><br /> <a :href="hrefs">简写的百度</a><br /> <a href="javascript:void(0);" v-on:click="domethod">摸我</a><br /> <a href="javascript:void(0);" @click="domethod">简写的摸我</a> <h2>7.过滤器(过滤器是JavaScript函数,因此可以接受参数)</h2> {{substrs|filterName}}<br /> {{substrs|subFilter|formatFilter}} <h2>8.计算属性(计算属性可用于快速计算视图(View)中显示的属性。这些计算将被缓存,并且只在需要时更新)</h2> <ol> <li v-for="stu in stus">{{stu.name}},{{stu.course}},{{stu.score}}</li> </ol> <p>总分:{{sum}}</p> <h3>9.监听属性(监听属性 watch,我们可以通过 watch 来响应数据的变化)</h3> <input type="text" v-model="mb" placeholder="请输入兆字节:MB"/> <input type="text" v-model="kb" placeholder="请输入千字节:KB"/> </div> <script type="text/javascript"> /* 全局过滤器 */ Vue.filter('filterName', function (value) { // value 表示要过滤的内容 return value.substring(0,6).toUpperCase(); }); /* 创建Vue实例 */ var vm = new Vue({ el: '#app', data: { ts: new Date().getTime(), title: '你好啊', sss: '<h4>这是html标签数据</h4>', binds: { backgroundColor: 'green', fontSize: '20px' }, id: '123', substrs: 'hello Vue ,这是我的第一个Vue实例!!!', number: 12, ok: false, sex: '女', flag: false, items: [{ id: 1, name: '张三' }, { id: 2, name: '李四' }, { id: 3, name: '王五' }, { id: 4, name: '赵六' }], stus:[{ course:'语文', name:'张三', score:90 },{ course:'数学', name:'张三', score:80 },{ course:'英语', name:'张三', score:91 },{ course:'理综', name:'张三', score:230 }], tes: 'test', checks: [], radio: '', hrefs: 'https://www.baidu.com', attr: 'href', evname: 'click', mb : '', kb : '' }, methods: { domethod() { alert('你已点击了一次'); }, goBaidu() { window.open('https://www.baidu.com'); } }, filters:{ subFilter(value){ return value.charAt(0).toUpperCase()+value.substring(1,9).toLowerCase(); }, formatFilter(value){ return value+fmtDate(new Date(),'yyyy年MM月dd日 hh:mm:ss'); } }, computed:{ sum(){ //var和let的区别 //var容易产生数据污染 let arr = this.stus; let sum = 0; for (let s of arr) { sum+=s.score; } return sum; } }, watch:{ kb(v){ console.log(v); return this.mb = this.kb/1024; }, mb(v){ console.log(v); return this.kb = this.mb*1024; } } }); </script> </body> </html>