目录
1.MVVM
2.options
3.生命周期
3.1生命周期函数
4.template
5.插值操作
6.计算属性
6.1计算属性的setter和getter方法
7.v-on事件监听
8.v-show
9.v-for
10.扩展
11.检查数组更新
12.v-model
13.组件化
14.全局组件与局部组件
15.父组件与子组件
16.注册组件语法糖
17.组件模板抽离
18.组件个性化数据存放
19.父子组件通信:父传子
20.父子组件通信:子传父
MVVM全称是:Model-View-ViewModel;
这里的View可以看做是HTML页面;
这里的Model可以看做是js对象,里面有服务器返回的数据;
这里的ViewMode可以看做是Vue,Vue因此主要有2个工作:DOM Listeners、Data Bindings,通过监听Model来实现数据驱动视图,通过监听DOM来实现HTML与数据同步变化;
https://cn.vuejs.org/v2/api/
官网自学,用到哪个,查哪个
https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA
绿色代表Vue自己的函数
红色代表Vue的回调函数
参考官网:
https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90
把HTML代码、Vue代码组成一个模板,然后直接使用就行了,类似于JAVA语言中公共模块;
Mustache:如何将data中的文本数据,插入到HTML中呢?这里涉及到Mustache语法,即双大括号,例如:{{message}}、{{firstname,’’ + lastname}};Mustache语言不仅可以直接写变量,还可以写简单的表达式,比如加减乘除等;
v-once
v-html
v-text
v-pre
v-cloak
v-bind:html属性,例如:v-bind:src=”XXX”
对象语法{class1:true,class2:false}
数组语法[class1,class2]
函数function(){return {class1:true,class2:false}}
V-bind:class=class
V-bind:style=CSS属性名
内联样式改为驼峰
Js语法不支持-
v-on:事件属性
在模板中可以直接通过插值语法来显示一些data属性中的数据,但在特定情况下,需要对数据进行一些转化后再显示,或者将多个数据结合起来进行显示,例如:{{firstname + secondname}}
computed属性可以解决这个问题;
computed:{
属性名:function(){...........}
}
使用的时候:{{属性名}}
注意:计算属性只计算运行一次,即无论调用几次,但只运行一次,后续也只是获取已经计算好的结果;
①每一个计算属性都包含一个setter和getter方法;
②只要属性不变,则计算属性的缓存也不变,因为,计算属性只计算一次,除非属性值发生变化;
绑定事件监听器,语法糖是:@
类型是function、object、inline statement
参数event
$event
修饰符:stop、prevent、keyCode、native、once等等
官网地址:https://cn.vuejs.org/v2/api/#v-on
v-show与v-if都会达到同样的效果,但其原理不一样:
v-show只是给元素添加一个行内样式:display:none,但元素还是存在于DOM结构中;而v-if则直接把元素从DOM中去掉;
对于切换频率比较高的时候,v-show性能更优秀;
v-for=”xx in 数组”
v-for=”(xx,index) in 数组”
v-for=”(value,key) in 对象”
v-for=”(value,key,index) in 对象”
假如数组arrays长度为1000,要求你在index=99的位置,插入一个新元素,此时你如何确保虚拟DOM的刷新性能?
这种编写方式,如果你在index=99的位置插入新数据,那么index>=100的后面的值,都要修改一遍,如果数组长度太大,则会影响虚拟DOM刷新性能;
为了解决这个问题,可以用下面这个写法:
这里加入了key这个属性,此刻Vue就会形成一个链表,这个链表存在着key-value形式的数据结构,此刻,当我在index=99插入新元素的时候,Vue直接找到这个位置,然后插入新元素,而index>=100的元素都不需要任何修改,从而节省资源;
总之,必须确保key的唯一性,key的作用就是为了更加高效的更新虚拟DOM,否则Vue会警告;
因为Vue是响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图也会发生对应更新,Vue中包含了一组观察数组编译的方法,从而改变数组时也会触发视图的更新:
push、pop、shift、unshift、splice、sort、reverse
Form表单提交,Vue中使用v-model指令来实现表单元素、数据的双向绑定;(即修改内存则刷新到HTML,HTML修改刷新到内存)
v-model其实是一个语法糖,背后包含2个指令:v-bind:value属性、v-on:input事件,其效果如下:
v-bind:value=”message”
v-on:input=”message = $event.target.value”
①当v-model与type=”radio”结合时,取值为普通值;
②当v-model与type=“checkbox”结合时,取值为数组;
v-model的修饰符,常用的如下:
①lazy修饰符:默认情况下,v-model默认是在input事件中同步输入框的数据,也就是说,一旦有数据发生改变,则对应的内存data中的数据就会立即自动发生改变,对于频繁修改数据的操作,会导致内存刷新频率比较高;
而lazy修饰符则可以让数据失去焦点/输入回车时,才回去刷新data;
②number修饰符:默认情况下,在输入框中,无论输入字母还是数字,都会被v-model当做字符串类型来进行处理;
如果我们希望用户输入的数字,被当做number来处理,而不是string类型来处理,则可以使用number修饰符;
number修饰符可以让在输入框中输入的内容自动转成数字类型,而不是String类型;
③trim修饰符:如果输入的内容,其首尾有很多空格,则可以使用trim修饰符来过滤内容首尾空格;
组件化开发步骤:创建组件构造器、注册组件、使用组件。
组件必须在Vue实例里面才能使用组件,因为只有在Vue实例里面才被Vue解析标签,否则,HTML解析器无法解析我们自定义的标签,毕竟HTML自定义标签与Vue的自定义组件还是有差别的;
全局组件:通过Vue.component来注册组件,可以在多个Vue实例下使用;
局部组件:通过Vue实例的components属性来注册组件,只能在当前Vue实例下使用;
首先编写子组件,再编写父组件,最后才是root组件
|
组件与组件之间,可以存在父子关系,当Vue渲染到父组件的template的时候,会从其components中获取子组件,然后再把子组件的template内容替换到父组件的template中;
Vue.component('XXXX',{组件的option对象});来替换Vue.extend
//创建组件构造器 const cpnC = Vue.extend({ template: ' 组件化开发}); //注册全局组件 // Vue.component('test_cpn',cpnC); Vue.component('test_cpn',{ template: ' 组件化开发});
//注册局部组件 // const cpnC1 = Vue.extend({ // template: ' 组件化开发-cpn1// }); const cpnC2 = Vue.extend({ template: ' 组件化开发-cpn2components: { cpn1: { template: ' 组件化开发-cpn1} } });
// root组件,即根组件 const app = new Vue({ el: '#app', components: { // test_cpn: cpnC, // cpn1: cpnC1, cpn2: cpnC2 } }); |
由于在JS代码区编写template代码比较繁琐,我们这里就把template代码的区域抽取出来,然后再挂载到对应的组件上,从而使得代码更加清晰;
Vue提供了2种方案来定义HTML模块内容:
①通过
id="cpn1">
Vue.component('cpn0',{
template: '#cpn0'
});
Vue.component('cpn1',{
template: '#cpn1'
});
// root组件,即根组件
const app = new Vue({
el: '#app'
});
组件无法访问Vue实例的data,所以,组件需要有存储自己数据的地方;
通过Vue组件的data属性来定义组件自己的数据,但需要注意2个地方:
①data属性必须是一个函数对象;
②data函数对象必须返回一个Object,Object内部存放数据;
{{title}}
{{title}}
Vue.component('cpn0',{ template: '#cpn0', data(){ return {title:'script标签抽离'} } }); Vue.component('cpn1',{ template: '#cpn1', data(){ return {title:'template标签抽离'} } }); // root组件,即根组件 const app = new Vue({ el: '#app' }); |
为什么组件的data属性必须是一个函数呢?
{{title}}
当前计数:{{counter}}
Vue.component('cpn0',{ template: '#cpn0', data(){ return {title:'script标签抽离'} } });
Vue.component('cpn1',{ template: '#cpn1', data(){ return {counter:0} }, methods: { increment(){ this.counter++; }, decrement(){ this.counter--; } } }); // root组件,即根组件 const app = new Vue({ el: '#app' }); |
当Vue组件的data为一个函数时,每一个Vue组件实例调用data的时候,由于data函数返回一个Object,这就可以保证了多个Vue组件都有自己独立的Object对象,类比于JAVA的对象内存地址,多个对象,其内存地址均不一样;
这里Vue组件
从上层组件传递数据到下层组件,还有子组件如何向父组件发送消息,这里为了解决这2问个问题,Vue官方提供了如下解决方法:
①父组件通过props向子组件传递数据;
②子组件通过emit事件向父组件发送消息;
当向子组件传递数据时,在子组件中,使用props选项来声明需要从父组件来接收的数据,props值有2种方式:
①字符串数组,数据中的字符串就是传递时的名称;
②对象,可以设置传递时的类型,也可以设置默认值,当需要对props进行类型校验的时候,就需要这种写法,校验的类型支持:string、number、boolean、array、object、date、function、symbol;
注意:v-bind不支持驼峰命名规则,到时候需要把驼峰命名分割成以“-”连接,例如:v-bind:child-my-message=”message”
使用步骤:
①在子组件中定义props选项;
②在子组件template中使用props选项中定义的数据;
③在Vue父实例绑定的HTML代码中,通过v-bind来指定props中自定义属性,与Vue父实例中data属性的映射关系;
子组件是通过“事件”的方式来向父组件传递数据;
开发步骤如下:
①在子组件的template中的代码中,通过@HTML事件来指定处理方法;
②在子组件的methods中定义事件,function体中通过this.$emit(事件名称,参数)来向父组件发射事件;
④在父组件绑定的HTML中,通过v-on:事件名称=“xxxxx”来指定父组件需要对应接受的方法;
⑤在父组件的methods中定义xxxxx的实现;
⑥至于子组件传递的参数,Vue默认会把emit中的参数传递过去,不需要在Vue父组件绑定的HTML中显式传入代码;之前会默认传递event,那是因为监听的事件是HTML的事件,而这个事件是自定义的事件,不属于HTML范畴;
{{title}}
const cpn_father =Vue.component('test_cpn',{ template: '#cpn_template', data(){ return {title: '这是自定义的子组件'} }, props:{ cpn_movies:{ type:Array, required:true, default(){ return ['自定义组件的movies默认值']; } } }, methods: { itemclick(item){ console.log('这是自定义组件的单击事件',item); this.$emit('fatherclick',item); } } }); const root = new Vue({ el: '#app', data: { movies:['进击的巨人','海贼王','火影忍者','数码宝贝'] }, components: { cpn_father }, methods: { fatherclick2(item){ console.log('这是自定义组件发给父组件的事件',item); } } }); |