拆解一个vue.js实例进行分析
前期工作我们做这样一件事情: 第一步:创建一个html 文件index.html 第二步:引入远程的vue的CDN文件 第三步:在body中书写楼下代码段 <div id="app"> <input type="text" name="" v-model="message" id=""><br /> <p>{{message}}</p> </div> 紧接着我们就开启我们的探索吧! 探索发现如何绑定一个Vue实例,或者说如何创建一个vue实例并挂载到对应节点?方法一:el方式为实例提供挂载方式,比如说这里我要把它挂载在id为app的div元素上,那就需要这么些el: '#app' 这里还需要明确的一点是你可以这样写 let vm = new Vue({ el: "#app", data: { message: "just do it!" } }) 你也可以这样写 new Vue({ el: "#app", data: { message: "just do it!" } }) 方法二:mount挂载let vm = new Vue({ data: { message: "just do it!" } })
vm.$mount('#app'); 关于template 在html中的应用,跟layui其实蛮像的,在这点上我们还是改造楼上的例子,创建一个script脚本 <script id="tpl" type="x-template"> <div class="tpl"> <p>祝大家新春快乐!</p> </div> </script> 然后对应的vue实例改成这样 let vm = new Vue({ el: "#app", data: { message: "just do it!" }, template: '#tpl' }) 你会发现这样一个现象,我本来时挂载到id为app的div上的,但是它并没有这么做。 关于数据data属性
最开始我们讲了,挂载实例的两种方式,不知你是否注意到我在el那里贴了两段接近一样的话,其中后者你不好在浏览器或者其他代码块去访问一些像data的属性,这里提一下吧。 关于data的写法你可以这样写 data: { message: "just do it!" } 你也可以这样写 data() { return { message: "just do it!" } } 这里我们着重看第一种写法,它是一个对象吧。那么这里想要搞事情,我们自然而然地想去实例外部创建一个对象然后赋值给data里面地属性来进行观察对吧,那开始吧。 把它改造成如楼下这样,笔者分别选了对象、数组、数值、字符串 let arr = [2, 0, 2, 0]; let obj = { name: 'ataola', age: 23 }; let str = 'hello world'; let num = 1997; let vm = new Vue({ el: "#app", data: { message: "just do it!", arr, obj, str, num } }) 可以看到笔者把数据搞到了data上。。。。。。 那我们接下来要做的事情可能同学们已经猜到了,改值呗,看看两者的变化。
这里提一下如果是你要获取data里面的元素,那么就需要vm.$data.message 这样写,或者直接vm.message 。 由于楼上那张图已经很明了地介绍了vue实例中data的情况,那么接下来我们再看看原先我们声明的变量吧,记住它的模样,原先它长这样,后面就可能被我改的不知道啥鬼样了。。。。。。 这里希望读者注意下,就是除了message是页面用到的,其他页面都没啥卵用,注意你更新了页面会变化吗?在这里其实vue内部是做了优化的。基于MVVM模型,就是说页面相关的数据改变了我才更新视图。
可以看到vue中的data对传入的对象只是进行了浅拷贝,就是说你改变了外面的其实也会影响vue里面的data里面的对象。
这里留一个坑吧,可能后续也会整理到我的vue疑问专题,就是说找茬嘛,我就要它深拷贝,有没有办法?有兴趣的同学思考下告诉我! 还有一个要提及一下就是怎么将数据和视图进行绑定。 如果其是一个块状元素,例如p,那么你大可<p>{{message}}</p> 这样搞, 如果说是一个表单元素,那么你可以用v-model ,不过这个在早期vue版本并没有这个属性。 这里提及一下,你可以通过vue.$set('key', 'val') 去增加一个变量,但是会报错 [Vue warn]: Cannot set reactive property on undefined, null, or primitive value: key
所以推荐你一开始就设计下,不要想到啥用啥,个人比较不喜欢和这种程序员共事,贼心累贼头大。 组件组件是一个蛮沉重的话题,我们不断地去学习一些技术框架,最后都应该以组件地形式输出,所以意义重大,这个在后面地专题应该会进行深入探讨,这里就意思下。 我们做这样一件事,创建一个组件 <div id="taola"> <taola-component title="3.1415926535" content="山顶一寺一壶酒,两人我杀我"></taola-component> </div> <script> let taolaComponent = Vue.component('taola-component', { props: ['title', 'content'], data() { return { author: 'ataola' } }, template: '<div><h1>{{title}}</h1><p>{{content}}</p><p>{{auther}}</p></div>' }); new Vue({ el: '#taola' }) </script> 翻译到页面如楼下,这里我们注册了一个全局组件,然后知道下父子组件之间用props传值,所以你放到data里面的报错,渲染不上去。 报了个错
Property or method "auther" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https:///v2/guide/reactivity.html#Declaring-Reactive-Properties. Vue中的方法methods这部分内容深究下,关于this指向会在后面的专题介绍,这里就简单意思下做一个点击增加次数的案例 在html中加入 <button @click ="add" >被点击了{{count}}次</button> 在vue实例化中增加methods方法 methods: { add: function() { this.count++ } } 生命周期这个话题依旧很沉重,你若问我有哪些以目前的记忆力都能记得住,但深究下去去分析应用场景这个我不一定能够很好地回答,所以这里暂时先定个脉络,后面专题去深究具体w问题具体分析。 那我们就来看下一些主要的生命周期钩子函数吧。 没有什么图比官网来的更贴切实在的了 init: function () { console.log('2.0中 init更名为beforeCreate,所以你看不到!') }, beforeCreate: function () { console.log('beforeCreate: 在实例开始初始化时同步调用!'); }, beforeCompile: function () { console.log('2.0中已废弃,推荐楼下的created,所以你看不到!'); }, created: function () { console.log('created: 在实例创建之后调用!'); }, beforeMount: function () { console.log('beforeMount: 新增于2.0,先于mounted!'); }, compiled: function () { console.log('2.0中已经更名为mounted,所有你看不到!'); }, attached: function () { console.log('2.0中已经废弃,所有你看不到!') }, detached: function () { console.log('2.0中已经废弃,所有你看不到!') }, ready: function () { console.log('2.0中已经废弃,推荐mounted,所有你看不到!') }, mounted: function () { console.log('mounted: 指令生效,DOM更新,但不保证$el已插入文档!') }, beforeDestroy: function () { console.log('beforeDestroy: 在开始销毁实例时调用,此时实例仍然有效!') }, destroyed: function () { console.log('destroyed: 在实例销毁后调用,实例和子实例被销毁,解绑了!') }, beforeUpdate: function() { console.log('beforeUpdate: 2.0中新增!'); }, updated: function() { console.log('updated: 2.0中新增!'); }, activated: function() { console.log('activated: 2.0中新增,需配合kepp-live!'); } 反映到浏览器中如下: 过滤器
Vue.js 允许在表达式后添加可选的过滤器,以管道符“|”指示, 例如 {{ name | uppercase }} // VUE 是个vue内置过滤器capitalize:字符串首字符转化成大写 uppercase :字符串转化成大写 lowercase :字符串转化成小写 currency 参数为{String}[ 货币符号] ,{Number} [ 小数位],将数字转化成货币符号,并且会自动添加数字分节号。 pluralize 参数为{String} single, [double, triple],字符串复数化。 json 参数为{Number}[indent] 空格缩进数,与JSON.stringify() 作用相同,将json对象数据输出成符合json 格式的字符串。 debounce 传入值必须是函数,参数可选,为{Number}[wait],即延时时长。作用是当调用函数n 毫秒后,才会执行该动作,若在这n 毫秒内又调用此动作则将重新计算执行时间。 limitBy 传入值必须是数组,参数为{Number}limit,{Number}[offset], limit 为显示个数,offset 为开始显示数组下标。 filterBy 传入值必须是数组,参数为{String | Function} targetStringOrFunction,即需要匹配的字符串或函数(通过函数返回值为 true 或 false 来判断匹配结果);“in”( 可选分隔符);{String}[…searchKeys],为检索的属性区域。 orderBy 传入值必须是数组,参数为{String|Array|Function}sortKeys,即指定排序策略。
PS: 2.0已经移除了这些内置过滤器 指令(Directives)这些很死,记记背背的东西,抓重点形如v-xxx 这种大致就是指令了或者@xx ,这边就不展开了,还是后面开个专题吧! 值得一提的是修饰符,就是说可以这样写v-on:click.stop="doClick" , stop相到于e. stopPropagation(), 望须知! 类似的有 .stop: 等同于调用event. stopPropagation()。 .prevent: 等同于调用event.preventDefault()。 .capture: 使用capture 模式添加事件监听器。 .self: 只当事件是从监听元素本身触发时才触发回调。 计算属性computed举个例子吧,写过markdown的同志应该有感触,一些应用可以让你边写边实时渲染,它做的就是这么个事情,监听属性的变化。 写法上形如这种: computed: { fun: { set: function(){
}, getL function() {
} }, func2: function() {
} } 这里我们在html中编写如下代码: <input type="text" name="" v-model="message" id=""><br /> <p>{{message}}</p> <input type="text" name="" v-model="message2" id=""><br /> <p>{{message2}}</p> <p>{{m1m2}}</p> 在vue的computed属性中这么写: data: { message: "just do it!", message2: "ataola is me !", }, computed: { m1m2: function() { return this.message + " | " + this.message2; } } 效果如图所属: 其实真正好玩的是,用计算属性的set和get去操作一些DOM、cookie、sessionStorage、localStorage之类的,这里就意思下,在后面专题我们再深究。
Class与Style绑定开发中经常做的一件事就是动态地增加或者删除类,比如说tab组件的切换。 这里比如说你在一个标签中运用了v-bind:classs="v-bind:calss="{'active' : active , 'unactive' : !active}" , 那么你只需要在data属性里设置active为true就行了。 渲染的结果就是 <div class="tab active"></div> 如果是多个类可以以数组的方式传递 v-bind:class="[classA, classB]" 如果你要绑定样式用v-bind:style ,用法和楼上一样,注意绑定的是内联样式,还有个好处就是它会帮你加前缀。 模板渲染模板渲染这块内容会涉及到一些遍历指令,你想嘛,大致就是拿个对象数组字段集合哈希表进行遍历输出显示嘛,早期前端做的是静态页面,死的数据,而模板的渲染这块要靠后端的嵌入php、jsp、asp代码完成,但现在更多的是后端给个接口,前端通过Ajax进行异步交互获取数据然后进行模板渲染,前后端更加专注做自己的事了吧,然后就是符合数据驱动视图。 Vue.extend(options)创建基础Vue 构造器的“子类”,参数options 对象和直接声明Vue 实例参数对象基本一致 大致如下写法 let Child = Vue.extend({ // coding });
Vue.component('ataola-child', Child); <ataola-child></ataola-child> 参考文献《Vue.js前端开发快速入门与专业应用》 组件基础:https://cn./v2/guide/components.html 组件注册:https://cn./v2/guide/components-registration.html 参考文献:https://cn./v2/guide/instance.html#%E5%AE%9E%E4%BE%8B%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD% 选自《Vue涂鸦》系列文章 原文地址:https://github.com/ataola/vue-Graffiti/blob/master/note/vue-normal.md
|