拆解一个vue.js实例进行分析
我们做这样一件事情:
第一步:创建一个html
文件index.html
第二步:引入远程的vue的CDN文件
第三步:在body中书写楼下代码段
<div id="app">
<input type="text" name="" v-model="message" id=""><br />
<p>{{message}}</p>
</div>
紧接着我们就开启我们的探索吧!
el: '#app'
这里还需要明确的一点是你可以这样写
let vm = new Vue({
el: "#app",
data: {
message: "just do it!"
}
})
你也可以这样写
new Vue({
el: "#app",
data: {
message: "just do it!"
}
})
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上的,但是它并没有这么做。
最开始我们讲了,挂载实例的两种方式,不知你是否注意到我在el那里贴了两段接近一样的话,其中后者你不好在浏览器或者其他代码块去访问一些像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://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
这部分内容深究下,关于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
PS: 2.0已经移除了这些内置过滤器
这些很死,记记背背的东西,抓重点形如v-xxx
这种大致就是指令了或者@xx
,这边就不展开了,还是后面开个专题吧!
值得一提的是修饰符,就是说可以这样写v-on:click.stop="doClick"
, stop相到于e. stopPropagation(), 望须知!
类似的有
.stop: 等同于调用event. stopPropagation()。
.prevent: 等同于调用event.preventDefault()。
.capture: 使用capture 模式添加事件监听器。
.self: 只当事件是从监听元素本身触发时才触发回调。
举个例子吧,写过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之类的,这里就意思下,在后面专题我们再深究。
开发中经常做的一件事就是动态地增加或者删除类,比如说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 构造器的“子类”,参数options 对象和直接声明Vue 实例参数对象基本一致
大致如下写法
let Child = Vue.extend({
// coding
});
Vue.component('ataola-child', Child);
<ataola-child></ataola-child>
《Vue.js前端开发快速入门与专业应用》
组件基础:https://cn.vuejs.org/v2/guide/components.html
组件注册:https://cn.vuejs.org/v2/guide/components-registration.html
参考文献:https://cn.vuejs.org/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