Vue语法

1.vue模板语法2大类

插值语法:

  • 功能:用于解析标签内容

  • 用途:用于标签内容定义

  • 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性

指令语法:

  • 功能:用于解析标签(包括:标签属性,标签内)

  • 用途:用于属性定义

  • 举例:v-bind:href=“xxx”或简写为:href=“xxx”,xxx同样要写js表达式,且可以直接读取到dta中的所有属性

代码

{{msg}}

   BUPT    BUPT

2. el与data的两种写法

初识Vue:

  1. 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;

  2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;

  3. root容器里的代码被称为【Vue模板】;

  4. Vue实例和容器是一一对应的;

  5. 真实开发中只有一个Vue实例,并且会配合着组件一起使用;

  6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;

  7. 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;

注意区分:js表达式 和 js代码(语句)

1. 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
            (1) a
            (2) a+b
            (3) demo(1)
            (4) x === y ? 'a' : 'b'
2. js代码(语句)
            (1) if(){}
            (2) for(){}

2.1 el有2种写法

  • new Vue时候配置el属性

  • 先创建Vue实例,随后再通过vm.$mount('#root')指定el的值

代码

2.2 data有2种写法

  • 对象式

  • 函数式

  • 在组件中,data必须使用函数式

2.3.一个重要的原则

由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了,而是window对象。

代码

完整代码如下:



    
        
        el与data的两种写法
        
        
    
    
        
        

你好,{{name}}

3. methods

先写个methods的例子


    
       

欢迎来到{{name}}学习

           

问题:

showInfo能否传递参数?对其加上参数后输出,可以看到形参a有输出为event。
showInfo(a,b,c,d){
    console.log(a,b,c,d)
}

e.target就是发生事件的事件目标,也即是button
showInfo(e){
    console.log(e.target.innerText)
}

可输出button上的文字。

this指针指向

showInfo(e){
	console.log(this)
}
//this指向vue实例。

v-on有简写形式如下

欢迎来到{{name}}学习

showInfo传参如下:

事件的基本使用: 1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名; 2.事件的回调需要配置在methods对象中,最终会在vm上; 3.methods中配置的函数,不要用箭头函数!否则this就不是vm了; 4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象; 5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;



	
		
		事件的基本使用
		
		
	
	
		
		

欢迎来到{{name}}学习

事件修饰符

Vue中的事件修饰符: 1.prevent:阻止默认事件(常用); 2.stop:阻止事件冒泡(常用); 3.once:事件只触发一次(常用); 4.capture:使用事件的捕获模式; 5.self:只有event.target是当前操作的元素时才触发事件; 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;



	
		
		事件修饰符
		
		
	
	
		
		

欢迎来到{{name}}学习

点我提示信息 点我提示信息

阻止事件冒泡:


	
	事件修饰符
	
	
    


	
	

欢迎来到{{name}}学习

点我提示信息
点我提示信息

键盘事件



	
		
		键盘事件
		
		
	
	
		
		

欢迎来到{{name}}学习

methods: {
    showInfo(e){
        if (e.keyCode !== 13)  return
        console.log(e.target.value)
    }
}

不用自己判断,去掉if (e.keyCode !== 13) return,可简化为


其中,.enter为按键别名。Vue中常用按键别名如下

  1. Vue中常用的按键别名: 回车 => enter 删除 => delete (捕获“删除”和“退格”键) 退出 => esc 空格 => space 换行 => tab (特殊,必须配合keydown去使用) 上 => up 下 => down 左 => left 右 => right 可在以上代码中换成其他按键别名尝试。 如没有这些按键别名,则需要自行定义。 tab键特殊,必须配合keydown去使用,因为tab键在按下时就跳离开了对应的元素。

  2. Vue未提供别名的按键,e.key,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

  3. 系统修饰键(用法特殊):ctrl、alt、shift、meta (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。 (2).配合keydown使用:正常触发事件。

    此时会每按次键在console中显示一次。但应该是所有内容输入完毕后再输出到console。 用JS完成如下

(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。


如果需要指定具体的组合,ctrl+y来触发,则写法如下

(2).配合keydown使用:正常触发事件。


修饰符可以连续写,既阻止跳转又阻止冒泡。修饰符顺序可以任意。



4. 计算属性

插值方式

全名示例

 

 	
	 
	姓名案例_插值语法实现 	
	 	
	 
 
 	
	  
	
姓:

名:

全名:{{firstName}}-{{lastName}}

提个需求,如firstName只要3位,其余位数不要,则代码如下:

姓:

名:

全名:{{firstName.slice(0,3)}}-{{lastName}}

但全名此部分过于复杂,可用methods实现。

1.methods方式


	
		
	姓名案例_methods实现	
		
	


	
	
姓:

名:

全名:{{fullName()}}
2.Computed方式
  • data中配置的键值对就是属性

  • 定义:要用的属性不存在,要通过已有属性计算得来。由姓和名计算出来全名,需要一个全新的配置项computed。

  • 原理:底层借助了Objcet.defineProperty方法提供的getter和setter

  • get函数什么时候执行?

  • (1).初次读取时会执行一次

  • (2).当依赖的数据发生改变时会被再次调用

  • 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便

  • 备注:

  • 计算属性最终会出现在vm上,直接读取使用即可

  • 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变

计算属性完整版写法


姓: 名: 全名:{{fullName}}

计算属性简写--只考虑读取计算属性值,不考虑设置计算属性值才可以用简写形式


姓: 名: 全名:{{fullName}}

注意:不能使用{{fullName()}}方式调用。在computed中的fullName()不是函数,是执行完这个函数后向vm这个实例上的fullName属性赋值。

5.watch监视属性

新建案例天气案例


今天天气很{{info}}

如果需要监视isHot的改变,实现监视需要配置对象watch,

watch:{
	isHot:{
		immediate: true, // 初始化时让handler调用一下,先不写这行,handler演示后再写这行。
		// handler什么时候调用?当isHot发生改变时。
		handler(newValue, oldValue){
			console.log('isHot被修改了',newValue,oldValue)
		}
	}
} 

监视属性watch:

  • 当被监视的属性变化时, 回调函数自动调用, 进行相关操作

  • 监视的属性必须存在,才能进行监视。如计算属性也可监视,可将

watch:{
	info:{
		immediate: true, // 初始化时让handler调用一下
		// handler什么时候调用?当isHot发生改变时。
		handler(newValue, oldValue){
			console.log(' info被修改了',newValue,oldValue)
		}
	}
} 

●监视的两种写法:

  • (1).new Vue时传入watch配置

  • (2).通过vm.$watch监视


今天天气很{{ info }}

深度监视:

  • (1).Vue中的watch默认不监测对象内部值的改变(一层)

  • (2).配置deep:true可以监测对象内部值改变(多层)

备注:

(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以

(2).使用watch时根据数据的具体结构,决定是否采用深度监视




    
    天气案例_深度监视 
    


    
    

今天天气很{{info}}


a的值是:{{numbers.a}}

b的值是:{{numbers.b}}

{{numbers.c.d.e}}

监视属性简写

不需要immediate和deep时,就可以使用简写形式。




    
    天气案例_深度监视 
    


    
    

今天天气很{{info}}


a的值是:{{numbers.a}}

b的值是:{{numbers.b}}

{{numbers.c.d.e}}

computed和watch之间的区别:

  • computed能完成的功能,watch都可以完成

  • watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作

两个重要的小原则:

  1. 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象

  2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。




    
    姓名案例_watch实现 
    


    
    
姓: 名: 全名:{{fullName}}

1. 过滤器(非重点)

定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。

语法:

  • 注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}

  • 使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"



	
		
		过滤器
		
		
	
	
		
		

显示格式化后的时间

现在是:{{fmtTime}}

现在是:{{getFmtTime()}}

现在是:{{time | timeFormater}}

现在是:{{time | timeFormater('YYYY_MM_DD')}}

备注:

  1. 过滤器也可以接收额外参数、多个过滤器也可以串联

  2. 并没有改变原本的数据, 是产生新的对应的数据

2.绑定样式

class样式

写法::class="xxx" xxx可以是字符串、对象、数。 所以分为三种写法,字符串写法,数组写法,对象写法 绑定样式:

  1. class样式 写法:class="xxx" xxx可以是字符串、对象、数组。 字符串写法适用于:类名不确定,要动态获取。 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

  2. style样式 :style="{fontSize: xxx}"其中xxx是动态值。 :style="[a,b]"其中a、b是样式对象。

字符串写法

字符串写法适用于:类名不确定,要动态获取。



	
		
		绑定样式
		
		
	
	
		
		
{{name}}


数组写法

数组写法适用于:要绑定多个样式,个数不确定,名字也不确定。



       
{{name}}

对象写法

对象写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。



{{name}}

style样式

有两种写法,对象写法,数组写法

对象写法


 
{{name}}

数组写法


 
{{name}}

整体代码如下:



	
		
		绑定样式
		
		
	
	
		
		
{{name}}


{{name}}


{{name}}


{{name}}


{{name}}

3. 收集表单数据(v-model)

案例如下:

若:,则v-model收集的是value值,用户输入的就是value值。


   
        账号:

       密码:

           

若:,则v-mdel收集的是value值,且要给标签配置value值。


 
性别: 男

若:

  1. 没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)

  2. 配置input的value属性:

    • v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)

    • v-model的初始值是数组,那么收集的的就是value组成的数组


爱好: 学习 打游戏 吃饭

所属校区

其他信息:

阅读并接受 《用户协议》

备注:v-model的三个修饰符:

  • lazy:失去焦点再收集数据

  • number:输入字符串转为有效的数字

  • trim:输入首尾空格过滤

可加入年龄一行,加入三个修饰符后完整代码如下:




    
    收集表单数据
    


    
    
账号:

密码:
年龄:

性别: 

爱好: 学习 打游戏 吃饭 

所属校区

其他信息:

阅读并接受 《用户协议》
   

4. 内置指令

1 .v-text指令:(使用的比较少)

  1. 作用:向其所在的节点中渲染文本内容。

  2. 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。


   
你好,{{name}}
   
   

2 .v-html指令:(使用的很少)

  1. 作用:向指定节点中渲染包含html结构的内容。

  2. 与插值语法的区别:

  • v-html会替换掉节点中所有的内容,{{xx}}则不会。

  • v-html可以识别html结构。

3.严重注意:v-html有安全性问题!!!!

  • 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。

  • 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!


   
你好,{{name}}
   

3. v-bind指令(没有值):

实现单向数据绑定

   
 

使用v-bind:value,则使得value后的msg作为js表达式,而不是字符串。

4 .v-on

5 .v-for

  • 用于展示列表数据

  • 语法:v-for="(item, index) in xxx" :key="yyy"

  • 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)

       

人员列表(遍历数组)

   
           
  •             {{p.name}}-{{p.age}}        
  •    
 

汽车信息(遍历对象)

   
           
  •             {{k}}-{{value}}        
  •    
 

测试遍历字符串(用得少)

   
           
  •             {{char}}-{{index}}        
  •    
  

测试遍历指定次数(用得少)

   
           
  •             {{index}}-{{number}}        
  •    

1.条件渲染

v-if

  • (1).v-if="表达式"

  • (2).v-else-if="表达式"

  • (3).v-else="表达式"

  • 适用于:切换频率较低的场景

  • 特点:不展示的DOM元素直接被移除

  • 注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”


欢迎来到{{name}}

欢迎来到{{name}}

Angular
React
Vue
哈哈

v-show

  • undefined 写法:v-show="表达式"

  • undefined 适用于:切换频率较高的场景

  • undefined 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉(display:none)

备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到

v-if 是实打实地改变dom元素,v-show 是隐藏或显示dom元素


欢迎来到{{name}}

欢迎来到{{name}}

2.学生列表案例

示例图如下:




  
  Document
  


  
班级 姓名 性别 年龄
{{item.grade}} {{item.name}} {{item.gender}} {{item.age}}

3. 生命周期

简介生命周期

Vue 实例有⼀个完整的⽣命周期,也就是从new Vue()、初始化事件(.once事件)和生命周期、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期。

先来一张尚硅谷的图:

  1. beforeCreate(创建前):数据监测(getter和setter)和初始化事件还未开始,此时 data 的响应式追踪、event/watcher 都还没有被设置,也就是说不能访问到data、computed、watch、methods上的方法和数据。

  2. created(创建后):实例创建完成,实例上配置的 options 包括 data、computed、watch、methods 等都配置完成,但是此时渲染得节点还未挂载到 DOM,所以不能访问到 $el属性。

  3. beforeMount(挂载前):在挂载开始之前被调用,相关的render函数首次被调用。此阶段Vue开始解析模板,生成虚拟DOM存在内存中,还没有把虚拟DOM转换成真实DOM,插入页面中。所以网页不能显示解析好的内容。

  4. mounted(挂载后):在el被新创建的 vm.$el(就是真实DOM的拷贝)替换,并挂载到实例上去之后调用(将内存中的虚拟DOM转为真实DOM,真实DOM插入页面)。此时页面中呈现的是经过Vue编译的DOM,这时在这个钩子函数中对DOM的操作可以有效,但要尽量避免。一般在这个阶段进行:开启定时器,发送网络请求,订阅消息,绑定自定义事件等等

  5. beforeUpdate(更新前):响应式数据更新时调用,此时虽然响应式数据更新了,但是对应的真实 DOM 还没有被渲染(数据是新的,但页面是旧的,页面和数据没保持同步呢)。

  6. updated(更新后) :在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。此时 DOM 已经根据响应式数据的变化更新了。调用时,组件 DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

  7. beforeDestroy(销毁前):实例销毁之前调用。这一步,实例仍然完全可用,this 仍能获取到实例。在这个阶段一般进行关闭定时器,取消订阅消息,解绑自定义事件。

  8. destroyed(销毁后):实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务端渲染期间不被调用。

引出生命周期:



	
		
		引出生命周期
		
		
	
	
		
		
		

你好啊

欢迎学习Vue

mounted()钩子函数的运行时机,Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted。

各个生命周期展示

1.beforeCreate(创建前)

数据监测(getter和setter)和初始化事件还未开始,此时 data 的响应式追踪、event/watcher 都还没有被设置,也就是说不能访问到data、computed、watch、methods上的方法和数据。



	
		
		分析生命周期
		
		
	
	
		
		

当前的n值是:{{n}}

这里没有n,也没有add()函数。

2.created(创建后)

实例创建完成,实例上配置的 options 包括 data、computed、watch、methods 等都配置完成,但是此时渲染得节点还未挂载到 DOM,所以不能访问到 $el属性。



	
		
		分析生命周期
		
		
	
	
		
		

当前的n值是:{{n}}

来讲一下图中间大框框的内容

先判断有没有 el 这个配置项,没有就调用 vm.$mount(el),如果两个都没有就一直卡着,显示的界面就是最原始的容器的界面。有 el 这个配置项,就进行判断有没有 template 这个配置项,没有 template 就将 el 绑定的容器编译为 vue 模板,来个对比图。

3.beforeMount(挂载前)

在挂载开始之前被调用,相关的render函数首次被调用。此阶段Vue开始解析模板,生成虚拟DOM存在内存中,还没有把虚拟DOM转换成真实DOM,插入页面中。所以网页不能显示解析好的内容。


    
    

当前的n值是:{{n}}

Vue已经完成解析,但没向页面挂载显示。

4.mounted(挂载后)

在el被新创建的 vm.$el(就是真实DOM的拷贝)替换,并挂载到实例上去之后调用(将内存中的虚拟DOM转为真实DOM,真实DOM插入页面)。此时页面中呈现的是经过Vue编译的DOM,这时在这个钩子函数中对DOM的操作可以有效,但要尽量避免。一般在这个阶段进行:开启定时器,发送网络请求,订阅消息,绑定自定义事件等等。



	
		
		分析生命周期
		
		
	
	
		
		

当前的n值是:{{n}}

5.beforeUpdate(更新前)

响应式数据更新时调用,此时虽然响应式数据更新了,但是对应的真实 DOM 还没有被渲染(数据是新的,但页面是旧的,页面和数据没保持同步呢)。


		
		

当前的n值是:{{n}}

需要点击button后,才会有以下效果。

此时要注意控制台上的n是2,页面上的n还是1。

6.updated(更新后)

在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。此时 DOM 已经根据响应式数据的变化更新了。调用时,组件 DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

updated() {
    console.log('updated')
    console.log(this.n)
    debugger   //调试命令
},

此时页面显示和data中的数据统一。

7.beforeDestroy(销毁前)

实例销毁之前调用。这一步,实例仍然完全可用,this 仍能获取到实例。在这个阶段一般进行关闭定时器,取消订阅消息,解绑自定义事件。


    
    

当前的n值是:{{n}}

可演示点击add按钮后再点击销毁按钮。

此时调用了bye方法和beforeDestroy钩子函数。

8.destroyed(销毁后)

实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务端渲染期间不被调用。

destroyed() {
	console.log('destroyed')
},

点击销毁后会被调用。

4.非单文件组件

  • 组件定义:实现应用中局部功能代码和资源的集合。包括结构、交互和样式。

  • 非单文件组件:一个文件中包含有n个组件。文件为html文件。

  • 单文件组件:一个文件中包含有一个组件。文件为vue文件。

新建html文件



	
		
		基本使用
		
	
	
		
		

学校名称:{{schoolName}}

学校地址:{{address}}


学生名称:{{studentName}}

学生年龄:{{age}}

现在要用组件的形式来写。从创建组件开始。

基本使用

Vue中使用组件的三大步骤:

  1. 定义组件(创建组件)

  2. 注册组件

  3. 使用组件(写组件标签)

定义组件

使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;

区别如下:

  1. undefined el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。

  2. undefined data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。

如何注册组件?

1.局部注册:靠new Vue的时候传入components选项 ​ 2.全局注册:靠Vue.component('组件名',组件)

编写组件标签:

讲解一下面试小问题:data必须写成函数:

这是 js 底层设计的原因:举个例子

对象形式

let data = {
    a: 99,
    b: 100
}
let x = data;
let y = data;
// x 和 y 引用的都是同一个对象,修改 x 的值, y 的值也会改变
x.a = 66;
console.loh(x); // a:66 b:100
console.log(y); // a:66 b:100

函数形式

function data() {
    return {
        a: 99,
        b: 100
    }
}
let x = data();
let y = data();
console.log(x === y); // false
// 我的理解是函数每调用一次就创建一个新的对象返回给他们

备注:使用template可以配置组件结构。

创建一个组件案例:Vue.extend() 创建或者直接创建对象


注册组件

  • 局部注册:靠new Vue的时候传入components选项

  • 全局注册:靠Vue.component('组件名',组件)

局部注册


全局注册


写组件标签



{{msg}}



对于全局组件,可再生成一个新的div#root2。因hello是全局注册的组件,因此可以在所有的vue实例中直接应用。

new Vue({ el:'#root2', })

几个注意点:

关于组件名:

一个单词组成:

  • 第一种写法(首字母小写):school

  • 第二种写法(首字母大写):School

多个单词组成:

  • 第一种写法(kebab-case命名):my-school

  • 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)

备注:

  1. (1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。

  2. (2).可以使用name配置项指定组件在开发者工具中呈现的名字。

关于组件标签:

  • 第一种写法:

  • 第二种写法:

备注:不用使用脚手架时,会导致后续组件不能渲染。

一个简写方式:

const school = Vue.extend(options) 可简写为:const school = options

组件的嵌套

比较简单,直接展示代码:

 

VueComponent

  • school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

  • 我们只需要写或,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)。

  • 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!(这个VueComponent可不是实例对象)

  • 关于this指向:

    • 组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。

    • new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

  • VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。Vue的实例对象,以后简称vm。

Vue 在哪管理 VueComponent

一个重要的内置关系

  • 一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype

  • 为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

1.21 单文件组件

单文件组件就是将一个组件的代码写在 .vue 这种格式的文件中,webpack 会将 .vue 文件解析成 html,css,js这些形式。

来做个单文件组件的案例:

School.vue






App.vue

用来汇总所有的组件(大总管)





main.js

在这个文件里面创建 vue 实例

import App from './App.vue'
new Vue({
	el:'#root',
	template:``,
	components:{App},
})

index.html

在这写 vue 要绑定的容器



	
		
		练习一下单文件组件的语法
	
	
		
		

6.Vuex

原理图:

6.1 概念

在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

6.2 何时使用?

多个组件需要共享数据时

6.3 搭建vuex环境

  1. 安装vuex3版本

    npm i vuex@3
    
  2. 创建文件:src/store/index.js

    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用Vuex插件
    Vue.use(Vuex)
    
    //准备actions对象——响应组件中用户的动作
    const actions = {}
    //准备mutations对象——修改state中的数据
    const mutations = {}
    //准备state对象——保存具体的数据
    const state = {}
    
    //创建并暴露store
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state
    })
    
  3. main.js中创建vm时传入store配置项

    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    
    //引入store
    import store from './store'
    
    //关闭Vue的生产提示
    Vue.config.productionTip = false
    //创建vm
    
      new Vue({
    
      	el:'#app',
    
      	render: h => h(App),
    
      	store,	
    
      })
    

App.vue




6.4 基本使用##

  1. 初始化数据、配置actions、配置mutations,操作文件store.js

      //引入Vue核心库
    
       import Vue from 'vue'
    
       //引入Vuex
    
       import Vuex from 'vuex'
    
       //引用Vuex
    
       Vue.use(Vuex)
    
       const actions = {
    
           //响应组件中加的动作
    
       	jia(context,value){
    
       		// console.log('actions中的jia被调用了',miniStore,value)
    
       		context.commit('JIA',value)
    
       	},
    
       }
    
       const mutations = {
    
           //执行加
    
       	JIA(state,value){
    
       		// console.log('mutations中的JIA被调用了',state,value)
    
       		state.sum += value
    
       	}
    
       }
    
       //初始化数据
    
       const state = {
    
          sum:0
    
       }
    
       //创建并暴露store
    
       export default new Vuex.Store({
    
       	actions,
    
       	mutations,
    
       	state,
    
       })
    
    

  1. 组件中读取vuex中的数据:$store.state.sum

  2. 组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)$store.commit('mutations中的方法名',数据)

    备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

具体案例:

1.不越过dispatch操作

App.vue





store/index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
	jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	}, 
	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		if(context.state.sum % 2){
			context.commit('JIA',value)
		}
	},
	jiaWait(context,value){
		console.log('actions中的jiaWait被调用了')
		setTimeout(()=>{
			context.commit('JIA',value)
		},500)
	}
}
//准备mutations——用于操作数据(state)
const mutations = {
	JIA(state,value){
		console.log('mutations中的JIA被调用了')
		state.sum += value
	},
	JIAN(state,value){
		console.log('mutations中的JIAN被调用了')
		state.sum -= value
	}
}
//准备state——用于存储数据
const state = {
	sum:0 //当前的和
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})

Count.vue







其他部分无变化。

由于actions中的jia和jian,没有做任何逻辑业务。因此可去掉,直接调用mutations中的JIA和JIAN。注意,此时要用commit,而不是dispatch。

去除jia和jian的index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		if(context.state.sum % 2){
			context.commit('JIA',value)
		}
	},
	jiaWait(context,value){
		console.log('actions中的jiaWait被调用了')
		setTimeout(()=>{
			context.commit('JIA',value)
		},500)
	}
}
//准备mutations——用于操作数据(state)
const mutations = {
	JIA(state,value){
		console.log('mutations中的JIA被调用了')
		state.sum += value
	},
	JIAN(state,value){
		console.log('mutations中的JIAN被调用了')
		state.sum -= value
	}
}
//准备state——用于存储数据
const state = {
	sum:0 //当前的和
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})

Count.vue







6.5 getters的使用

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。不是必须的配置项

  2. store/index.js中追加getters配置

    //该文件用于创建Vuex中最为核心的store
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用Vuex插件
    Vue.use(Vuex)
    
    //准备actions——用于响应组件中的动作
    const actions = {
    	/* jia(context,value){
    		console.log('actions中的jia被调用了')
    		context.commit('JIA',value)
    	},
    	jian(context,value){
    		console.log('actions中的jian被调用了')
    		context.commit('JIAN',value)
    	}, */
    	jiaOdd(context,value){
    		console.log('actions中的jiaOdd被调用了')
    		if(context.state.sum % 2){
    			context.commit('JIA',value)
    		}
    	},
    	jiaWait(context,value){
    		console.log('actions中的jiaWait被调用了')
    		setTimeout(()=>{
    			context.commit('JIA',value)
    		},500)
    	}
    }
    //准备mutations——用于操作数据(state)
    const mutations = {
    	JIA(state,value){
    		console.log('mutations中的JIA被调用了')
    		state.sum += value
    	},
    	JIAN(state,value){
    		console.log('mutations中的JIAN被调用了')
    		state.sum -= value
    	}
    }
    //准备state——用于存储数据
    const state = {
    	sum:0 //当前的和
    }
    //准备getters——新添加,用于将state中的数据进行加工
    const getters = {
    	bigSum(state){
    		return state.sum*10
    	}
    }
    
    //创建并暴露store
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state,
    	getters  //新添加
    })
    
    
  3. 组件中读取数据:$store.getters.bigSum

    Count.vue

    
    
    
    
    
    
    

6.6 四个map方法的使用

导入

import {mapState, mapGetters, mapActions, mapMutations} from 'vuex'

  1. mapState方法:用于帮助我们映射state中的数据为计算属性

    computed: {
        //借助mapState生成计算属性:sum、school、subject(对象写法)
         ...mapState({sum:'sum',school:'school',subject:'subject'}),
             
        //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject']),
    },
    
    
  2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性

    computed: {
        //借助mapGetters生成计算属性:bigSum(对象写法)
        ...mapGetters({bigSum:'bigSum'}),
    
        //借助mapGetters生成计算属性:bigSum(数组写法)
        ...mapGetters(['bigSum'])
    },
    
    
  3. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    
    
  4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

    methods:{
        //靠mapActions生成:increment、decrement(对象形式)
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),
        
        //靠mapMutations生成:JIA、JIAN(对象形式)
        ...mapMutations(['JIA','JIAN']),
    }
    
    

备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则传的参数是事件对象(event)。

具体案例:








你可能感兴趣的:(vue.js,javascript,ecmascript)