Vue基础(一)
Vue学习框架和类库前端从后端获取到数据之后,如何将其展示到页面上?原生DOM操作,将数据一个个的往上放字符串拼接法模板引擎数据驱动的MVVM框架Vue等这些框架做的事情,其实就是简化数据渲染的操作!提高开发效率的!!框架(Framework)框架是一整套完整的解决方案,我们需要将自己的代码按照框架的规则,放在合适的位置,框架会在合适的时机,帮我们调用代码...
Vue学习
框架和类库
前端从后端获取到数据之后,如何将其展示到页面上?
-
原生DOM操作,将数据一个个的往上放
-
字符串拼接法
-
模板引擎
-
数据驱动的MVVM框架
Vue等这些框架做的事情,其实就是简化数据渲染的操作!提高开发效率的!!
框架(Framework)
框架是一整套完整的解决方案,我们需要将自己的代码按照框架的规则,放在合适的位置,框架会在合适的时机,帮我们调用代码,实现指定的功能。(framework call you)
类库(Library)
类库是一系列方法的集合,在我们编程的时候,我们需要自己决定什么时候,调用哪个方法,实现什么功能。(you call library)
MV*框架
MV*模式指的其实就是对代码进行按照功能划分模块的方式!
MVC
-
Model: 和数据相关的代码,负责提供数据的!
-
View: 和展示相关的代码,负责展示数据的!
-
Controller: 负责将数据转交给视图,同样负责从视图中收集数据,转交给Model(需要程序员自己控制)
MVVM
-
Model、View:与MVC的是一样的
-
View-Model: 这个部分是由框架实现的,不需要程序员再进行开发了,就可以自动实现数据到视图,以及视图到数据的流程!
Vue是什么?
渐进式的JavaScript框架
渐进式(Progressive)
Vue的核心功能非常小,可以用来支撑小型的网页的开发,Vue还支持其他额外的一些插件,可以逐步的扩展框架的功能用以支撑大型企业级项目的开发。 由小到大演变的过程,其实就是所谓的渐进式。
Vue的使用
-
安装vue 通过npm 或者yarn(也可以直接去官网下载vue.js文件)
-
在页面中引入vue.js文件
-
在script标签中创建Vue的实例
const vm = new Vue({ // 当前vue实例要控制的元素范围,放元素的id el:'#app', data:{ // data中放的就是要在视图中展示的数据 name:'zs' } }) // 如果之前用过模板引擎的,比如art-template,这里就可以类比的来看 // art-template中使用的方式 template('模板id',对象类型的数据) `el: '#app'` // 相当于和页面建立了绑定关联 `data:{...}` // 相当于说绑定的那部分数据是什么
-
在HTML代码中创建视图对应的元素
-
在视图元素的范围内,通过插值表达式或者指令来使用Vue的功能
<div id='app'> <h1> {{name}} </h1> </div>
-
数据驱动(核心的理念)
什么是数据驱动? 就是通过控制数据的变化来改变某物或某事。
Vue的数据驱动中, 数据驱动什么? 就是说物或者事是什么? 这里的vue数据驱动的是视图也就是DOM元素让DOM的内容随着数据的改变而改变, 这里视图(DOM)可以理解成上面的改变的某物或者某事
如果想要操作页面元素的变化,不要再去想DOM操作了!!要想办法通过修改数据来达成效果!
插值表达式
可以看到我们上面使用{{name}}这样的方式把数据绑定到了页面上,这种语法我们叫做插值表达式
也叫做小胡子语法
表达式和语句怎么区分? (参考说明 https://zhuanlan.zhihu.com/p/38622128)
语句是为了进行某种操作,一般情况下不需要返回值,而表达式都是为了得到返回值,一定会返回一个值(这里的值不包括undefined)。
简单的理解就是:表达式指的就是有值得内容, 我们把他放到等号的右边,看能不能成立,如果可以,就是表达式
插值表达式中可以出现的内容
- {{data中的数据名}}
- {{ 1 }}
- {{ “字符串” }}
- {{ true }}
- {{ 数据名.方法}} {{name.toUpperCase()}}
插值这里存在一个问题——插值闪烁
原因:Vue加载太慢,没人处理插值表达式,直接原样显示在页面上,等Vue加载完了,才会处理,这时数据才会展示出来,会有闪烁的效果出现
解决方案: v-cloak
-
给元素添加v-cloak指令
<h1 v-cloak>{{name}}</h1>
-
在style标签中添加一个 v-cloak的属性选择器样式 display:none
[v-cloak]{ display:none }
解决的原理: 一开始先隐藏,当Vue加载完了,数据渲染完成,就把v-cloak删掉,数据就显示出来了!
数据的双向绑定
数据绑定,说的就是,将数据和视图关联起来
- 单向绑定: 当数据发生变化的时候,页面中的内容也会随之发生变化,而页面中的内容不会影响数据的变化
<!-- v-bind是一个单项绑定的指令 -->
<input type="text" :value="name">
-
双向绑定:当数据发生变化的时候,页面中的内容会随之变化,页面中的内容发生变化的时候,数据也会随之变化 双向绑定一般只会出现在表单元素中!
<!-- 双向绑定最实用的场景,就是获取用户在表单中输入的数据 --> <input type="text" v-model="name">
双向绑定原理
可以分为两部分,一部分是视图数据变化,如何去改变绑定的数据,另一部分是绑定的数据改变,如何去改变视图数据。
第一部分是很简单的,我们可以监听表单控件的input事件,就可以知道数据发生了修改,但是关键是第二部分,我们怎么知道绑定的数据修改了呢?
Object.defineProperty方法
// 1. 如何给对象添加一个属性? let obj = {name: ""} obj.age = 18; obj["gender"] = "male"; // Object.defineProperty可以用来给对象添加属性,也可以用来修改现有的属性 // 在添加属性的时候,可以设置属性以下的特性: // 1. 是否为只读属性 // 2. 是否可以删除 // 3. 是否可以遍历 // 4. 可以为属性注册像改变事件一样的函数 // Object.defineProperty(要添加或者修改属性的对象, 要添加或者修改的属性名, 特征对象) Object.defineProperty(obj, "name", { // 1. 默认的,该属性是只读的,不能被赋值 默认是false writable: true, // 2. 默认的,该属性不能被for in循环遍历 默认是false enumerable: true, // 3. 默认的,该属性不能被delete删除 默认是false configurable: true, // value属性用来设置属性的默认值 value: "123" }) let nameValue = ""; Object.defineProperty(obj, "name", { // set和get不能和上面的额writable,value同时出现 set(value){ // 这个函数就像是属性的改变事件,我们在给属性赋值的时候 // JS内部会自动调用这个函数 console.log("属性被赋值了"); // 在set函数中,需要接收用户所赋值的内容,也就是等号右边的内容 可以通过value形参接收 // 将其存储起来 nameValue = value; }, get(){ // 这个函数就像是属性的被获取的事件,只要有人用到这个属性了,那这个函数就会被调用 console.log("属性被获取值了") // 这个函数会在用户获取值得时候调用,用户获取到的值,就是当前函数的返回值 return nameValue; } })
通过Object.defineProperty 方法我们就可以像监听事件一样来监听绑定数据是何时修改的,然后把这个修改后的数据重新帮到表单控件上
let nameValue = ""; Object.defineProperty(obj, "name", { set(value){ input.value = nameValue = value; }, get(){ return nameValue; } })
计算属性(computed)
如果页面中需要某个数据,而这个数据是根据当前data中的数据计算出来的,那么我们就使用计算属性。计算属性的本质: 就是一个函数,这个函数会有一个返回值
-
计算属性的使用
<div id="app"> FirstName<input type="text" v-model="firstName"> LastName<input type="text" v-model="lastName"> <!-- 这里直接使用属性名就行了不用加小括号--> FullName<input type="text" v-model="fullName"> </div>
<script> const vm = new Vue({ el: "#app", data: { firstName: "", lastName: "" }, computed: { // 计算属性的属性名 fullName(){ return this.firstName + "·" + this.lastName } } }) </script>
- 计算属性的完整形式
//因为我们用v-model进行了双向绑定,所以我们就需要使用完整形式来类似于监听数据的修改(用set监听) fullName: { get(){ // 这个函数会在用户获取这个计算属性值得时候调用,返回值就是用户获取到的值 return this.firstName + "·" + this.lastName }, set(value){ // 这个函数会在用户为这个计算属性赋值的时候调用 // 在这个函数中,我们可以对fullname进行拆分 // value就是用户给这个计算属性赋的值 this.firstName = value.split("·")[0] this.lastName = value.split("·")[1] } } }
- 计算属性(computed)和方法(methods)的区别
- methods 可以传参,计算属性不能
- methods不一定有返回值,而计算属性必须有返回值
- 计算属性有缓存,如果页面中多次使用,只会调用一次计算属性的函数
- 如果用methods来实现计算属性的功能,他是没有缓存的,使用多次的时候,用几次调几次性能不好
侦听器(watch)
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过
watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
侦听器的使用
const vm = new Vue({
el: "#app",
data: {
msg: "hello world"
},
watch: {
// watch属性是一个对象,对象中的属性名就是要监视的数据(data中的)的名字
// 当这个数据发生变化的时候,这个函数会自动被执行
// 并且Vue提供了两个参数,newValue 是修改后的值, oldValue 是修改前的值
msg(newValue, oldValue){
console.log("msg发生变化了", newValue, oldValue)
}
}
})
侦听器完整形式
const vm = new Vue({
el: "#app",
data: {
person: {
name: "张学友",
age: 18
}
},
watch: {
// 如果要监视对象中的属性的变化,不能只写对象的名字
// 因为对象是个引用类型的数据,属性发生变化的时候,地址是不会变化的
// 地址不变化,监视就不生效
// 我们需要在监视属性的时候,将对象.属性名作为监视函数的名字,这样就能监视到属性的变化了
// 这么写是非常麻烦的,特别是针对属性特别多的时候,对于简单类型数据来说可以这么写
"person.name": function(newValue, oldValue){
console.log("person.name发生变化了", newValue, oldValue)
},
"person.age": function(newValue, oldValue){
console.log("person.age发生变化了", newValue, oldValue)
}
// watch的平时的写法只是一个简写形式,他还有一个完整形态
// 针对数组、对象这样的复杂类型需要如下这么写
person: {
handler(newValue, oldValue){
console.log("person变化了")
console.log(newValue, oldValue)
},
// 进行深度监视,只要对象的任意属性发生变化,都会触发这个监视函数
// 进行深度监视的时候,newValue和oldValue值一样,因为监视的是引用类型的值,newValue和oldValue指向的是同一个对象
deep: true,
// 这个属性设置的是,代码一开始运行,就执行一次handler函数!
immediate: true
}
}
})
filter(过滤器)
过滤器其实就是一个函数,允许你自定义过滤器,可被用于一些常见的文本格式化,过滤器可以用在两个地方:双花括号插值和 v-bind 表达式
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
<!--
带参数的过滤器(v-bind使用方式一样),过滤器的默认第一个参数就是 管道符 "|" 前面的表达式的值(要过滤的数据) 括号中添加的是第二次开始的参数
-->
{{ message | capitalize(arg1,arg2)}}
注:过滤器可以串联
{{ message | filterA | filterB }}
<!--
filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。
-->
-
定义全局过滤器
全局注册的过滤器,当前页面中所有的vue实例都可以使用
Vue.filter('过滤器名', function('要过滤的数据',arg1,arg2){ // 对过滤的数据进行加工后输出 return xxx })
-
定义局部过滤器
只在某个vue实例中生效(是私有的) 在创建vue实例的时候,参数对象中添加一个 filters属性,将过滤器函数注册在这个对象中即可
{{message | dateFormat('YYYY-MM-DD')}} <!-- 2019-06-18 -->
const vm = new Vue({ el:'#app', data:{ message:new Date() // Tue Jun 18 2019 20:20:33 GMT+0800 (中国标准时间) }, filters:{ // 第一个参数就是原始的日期,第二个参数是传递的需要的日期格式 dateFormat(data,pattern){ // 这里使用了moment.js这个库 return moment(data).format(pattern) } } })
自定义指令(directive)
有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令(自定义指令在实际开发中用的不多)
以Vue官网的Demo为例
<div id='app'>
<input type='text' v-focus>
</div>
可能会有疑问直接用autofocus这个不就能自动获取焦点了吗?但是这里是有问题的,当我们加了autofocus 这个属性后,界面一开始的确执行了这个属性,但是因为上面这部分代码是在Vue控制的区域中的,Vue自身生命周期会对这段代码进行编译,导致之前执行一次的autofocus不会再一次执行,因此不会起作用,因此需要用到自定义指令
-
全局自定义指令
// 注意:这里的指令名是不带 v- 的,但是界面上使用的时候需要带 v- Vue.directive('focus',{ // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } })
-
局部自定义指令
const vm = new Vue({ el:'#app', directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } } })
-
指令钩子函数
什么是钩子函数?钩子函数指的就是在特定的时机下触发的函数
Vue.directive('focus',{ bind(el,binding){ // 比较常用 // 在vue开始解析这个指令的时候执行的 // 在这里一般可以进行一些样式的设置,比如设置字体颜色、字体粗细等 }, inserted(el,binding){ // 在vue将当前指令所在的元素渲染到页面上的时候执行的 // 比如执行自动获取焦点的操作,需要在inserted中执行 }, update(el,binding){ // 比较常用 // 当当前指令绑定的数据发生变化的时候,页面元素还没有更新的时候调用 // 一般update中执行的和bind中执行的差不多,以此就有了后面的简写形式 }, componentUpdated(el,binding){ // 当当前指令绑定的数据发生变化的时候,页面元素更新全部完成时候调用 }, unbind(el,binding){ // 指令被卸载的时候调用 } })
钩子函数参数说明
- el: 表示的是当前的元素
- binding:一个对象
- name 指令名,不包括 v- 前缀。
- rawName 带v的指令名
- arg 传给指令的参数
- modifiers 一个包含修饰符的对象 ,修饰符对象为
{ foo: true, bar: true }
- expression =后面的表达式 这是一个字符串
- value 表达式对应的值
指令的简写形式
在很多时候,你可能想在
bind
和update
时触发相同行为,而不关心其它的钩子。比如这样写:Vue.directive('color-swatch', function (el, binding) { el.style.backgroundColor = binding.value }) const vm = new Vue({ el: '#app', data: { msg: 'hello world!' }, directives: { mytext(el, binding) { el.innerText = binding.value } } })
Vue实例生命周期
一个实例从开始到最后消亡所经历的各种状态,就是一个实例的生命周期
总体可以分为三个阶段:初始化阶段、更新(运行)阶段、销毁(卸载)阶段
生命周期
-
初始化阶段
- (Init Events & Lifecycle) 初始化事件和生命周期 (具体是什么事件参考这里)
- (Init injections & reactivity)初始化数据(把data中的数据通过Object.defineProperty加到Vue实例中),最先能访问到数据是在这个时候
- (Has “el” option?)判断当前创建Vue实例的时候传进来的参数中是否有el属性
- (Has ‘template option ?’)如果有,就继续判断是否有template属性
- (Compile template into render Function)如果有,就编译模板,创建一个render函数出来
- (Compile el’s outerHTML as template)如果没有,就把el对应的元素的html代码编译成模板(我们常见的代码要走这一步)
- (when vm. m o u n t ( e l ) i s c a l l e d ) 如 果 没 有 , 就 当 v m . mount(el) is called)如果没有,就当vm. mount(el)iscalled)如果没有,就当vm.mount被调用之后继续执行(我们常见的代码要走这一步)
- (Has ‘template option ?’)如果有,就继续判断是否有template属性
- (Create vm. e l a n d r e p l a c e ′ e l ′ w i t h i t ) 创 建 v m . el and replace 'el' with it)创建vm. elandreplace′el′withit)创建vm.el(里面的数据已经完全渲染好了), 并且用这个新创建的元素,把页面中的el给替换掉
这个时候,我们就在页面上看到了有数据的html元素了!!!
-
更新(运行)阶段
- (when data changes)Vue会监听数据的变化,当数据发生变化的时候
- (Virtual DOM re-render and patch)Vue会通过虚拟DOM重新渲染,对页面内容进行更新
-
销毁(卸载)阶段
- (when wm. d e s t r o y ( ) i s c a l l e d ) 当 v m . destroy() is called) 当vm. destroy()iscalled)当vm.destory被调用的时候
- (Teardown watches, child components and event listeners)会将所有的和当前vue实例相关的资源进行释放
生命周期钩子函数
-
create: 在数据初始化前后调用的事件
- beforeCreate
- created
-
mount: 在将有数据的元素挂载到页面前后调用的事件
- beforeMount
- mounted
-
update: 数据发生改变,页面更新前后调用的事件
- beforeUpdate
- updated
-
destroy: 当vm.$destroy被调用,资源释放前后调用的事件
- beforeDestroy
- destroyed
const vm = new Vue({
el:'#app',
data:{
msg:'hello world'
},
beforeCreate() {
// beforeCreate 数据初始化之前执行的,这时候还没数据
// console.log(this.msg);
console.warn("beforeCreate 被执行了")
},
created() {
// 能够访问数据最早的钩子函数,其实就是created
// 重点: 工作中最常用的就是这个钩子函数
// 页面一家在就要请求数据的ajax请求一般都在这里发送
// console.log(this.msg);
console.warn("created 被执行了")
},
beforeMount() {
// console.log(document.getElementById("app"));
console.warn("beforeMount 被执行了")
},
mounted() {
// console.log(document.getElementById("app"));
// 如果在实际开发当中,我们要访问有数据的DOM,那么久需要在mounted钩子函数里去做
console.warn("mounted 被执行了")
},
beforeUpdate() {
// 这里可以访问更新前的DOM
console.log(document.getElementById("app").innerHTML);
console.warn("beforeUpdate 被执行了")
},
updated() {
// 这里可以访问更新后的DOM
console.log(document.getElementById("app").innerHTML);
console.warn("updated 被执行了")
},
beforeDestroy() {
console.warn("beforeDestroy 被执行了")
},
destroyed() {
console.warn("destroyed 被执行了")
}
})
Vue实例的完整形式
根据需要添加相应的属性参数
const vm = new Vue({
el:'#app',
data:{
msg:'hello world!'
},
methods:{
// 定义函数、事件处理函数
fn(){}, // 简写方式
fn1:function(){}
},
computed:{
cmp(){return 数据},
cmp1:function(){return 数据},
// 完整形式,一般有双向绑定的时候会用到这完整形式
cmp:{
get(){
return 数据
},
set(value){
this.xxx = value
}
}
},
watch:{
msg(newValue, oldValue){
// msg数据改变的时候自动执行
},
// 完整形式
msg:{
handler(newValue, oldValue){
// msg数据改变的时候自动执行
},
deep:true, // 默认是false
immediate:true // 默认是false
}
},
filters:{
// 局部过滤器
// 参数一定死了是 管道符 "|" 前面的值
dateFormat(data,arg1,arg2){},
dateFormat:function(data,arg1,arg2){}
},
directives:{
// 局部自定义指令
mytext:{
// 指令钩子函数
bind(el,binding){},
inserted(el,binding){},
update(el,binding){},
componentUpdated(el,binding){},
unbind(el,binding){}
}
},
beforeCreate(){},
created(){},
beforeMount(){},
mount(){},
beforeUpdate(){},
updated(){},
beforeDestroy(){},
destroyed(){}
})
Vue指令
vue中内置了很多自定义的类似于html属性的东西(带有
v-
前缀的特殊特性),每个vue提供的这种属性都会对应一个特定的功能,这些类似于自定义属性的东西就叫做指令,职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
先定义一个Vue的实例,后面的指令都取值自这里
const vm = new Vue({
el:'#app',
data:{
msg:'hello world',
msg1:'<h1>hello world</h1>'
imageSrc:'./logo.png',
size:24,
isShow:true,
classA:{
red:true,
bd:false
},
divStyle1: "width: 100px; height: 100px; background-color: pink;",
divStyle2: {width: "100px", height: "100px", backgroundColor: "pink"},
divStyle3: {width: "50px", height: "50px", backgroundColor: "green"},
items:['zs','ls','ww'],
items1: [
{id:1, name: 'zs', age: 18 },
{id:2, name: 'ls', age: 24 },
{id:3, name: 'ww', age: 30 }
]
}
})
v-bind指令
在Vue中给标签的属性赋值数据的时候,不可以使用插值表达式,因此需要用到v-bind
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
<!-- class 绑定 -->
<!-- 可以给class属性绑定一个对象,对象中的每个属性名代表的就是对应的类名,属性的值为布尔值,如果是true,就代表当前的元素拥有该类样式,如果是false,就代表当前的元素没有该类样式 -->
<div id="box" :class="{red: true, db: true}"></div> <!-- 直接赋值 -->
<div id="box" :class="classA"></div> <!-- 从Vue实例中取值-->
<div :class="[classA, { classB: true, classC: false }]"> <!-- 可以是一个数组-->
<!-- style 绑定 -->
<div :style="divStyle1"></div>
<div :style="[divStyle2, divStyle3]"></div>
<!-- 如果数组中直接写类名需要用引号包裹,不然回去实例中找变量名 -->
<div :style="['red', 'db']"></div>
v-for指令
基于源数据多次渲染元素或模板块,可以实现数组/对象/字符串/数字/Iterable的遍历
<div v-for="item in items">
{{ item }}
</div>
<!-- item表示每一项 index表示对应的索引下标-->
<div v-for="(item, index) in items">{{item}} - {{index}}</div>
<!-- val表示对象的属性值 key表示对象的属性名 -->
<div v-for="(val, key) in object"></div>
<!-- 还可以如下使用,去获取每一项的id然后绑定给标签属性-->
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
<!-- 遍历一个数字 -->
<div v-for='item in 5'>
{{item}}
</div>
<!-- 遍历一个字符串-->
<div v-for='item in "hello"'>
{{item}}
</div>
v-for使用最好如下,与key配合使用
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
“就地更新”:当在进行列表渲染的时候,vue会直接对已有的标签进行复用,不会整个的将所有的标签全部重新删除和创建
<!-- 让生成的每一项有一个唯一的标识 -->
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
增加Key的好处
- 加了key属性之后可以提升列表的渲染性能
- 加了key属性之后可以避免数据混乱(只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出)
v-show指令
根据表达式之真假值,切换元素的
display
CSS 属性。
<!-- isShow=true 元素显示 isShow=false 标签增加display:none 不显示-->
<div id="box" v-show="isShow">hello world</div>
v-if指令
根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建,即为false是删除标签和标签数据,为true时重新创建标签和绑定数据
<!-- isShow=true 元素显示 isShow=false 标签被移除不显示-->
<div id="box" v-if="isShow">hello world</div>
v-show 和 v-if 比较
区别
- v-show如果条件是false,里面的所有的vue相关的指令照常进行解析和渲染了
- v-if如果条件是false,里面的所有的vue相关的指令都不会进行解析和渲染了
- v-show指令接受一个数据,如果数据是true则元素展示,否则元素隐藏
- v-if也能控制展示和隐藏,但是,他是直接将元素从页面dom树种移除掉了
应用场景
- v-show 用于简单的页面中的元素展示和隐藏切换比较频繁的场景!
- v-if用于只判断一次的场景,因为这个可以用来提高性能,比如管理员拥有的权限,如果是管理员,就展示,如果不是管理员就不展示,就用v-if
v-cloak指令
这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如
[v-cloak] { display: none }
一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。
<div v-cloak>
{{ message }}
</div>
[v-cloak] {
display: none;
}
v-text指令
更新元素的 内容
<span v-text="msg"></span>
<!-- 等价于-->
<span>hello world</span>
v-text指令和之前的插值表达式很像,但是两者有区别
- 插值表达式会存在插值闪烁问题,而v-text不会有
- 插值表达式值替换{{Mustache }}的内容,而v-text 会替换标签原本的内容
v-html指令
更新元素的
innerHTML
<div v-html='msg1'></div>
<!-- 等价于 -->
<div>
<h1>
hello world
</h1>
</div>
v-on指令
绑定事件监听器,事件类型由参数指定
<button v-on:click="btnClickHandler">点我呀!</button>
<div id="box" v-on:mouseenter="divMouseEnterHandler"></div>
<!-- v-on:事件名称="事件处理函数的名称" 事件处理函数是保存在methods属性中! -->
<!--事件注册的简写形式:-->
<!-- @事件名称="事件处理函数的名称" -->
<button @click="btnClickHandler">点我呀!</button>
<div id="box" @mouseenter="divMouseEnterHandler"></div>
<!-- 事件注册的时候,如果要给事件处理函数传递参数,那么我们直接给函数名称后面加上小括号,将参数放进去即可! -->
<button @click="btnClickHandler(100)">点我呀!</button>
<!--还可以使用箭头函数的写法-->
<!-- e.target对应的就是当前的文本框 -->
<input type="text" :value="name" @input="e => name = e.target.value">
调用的事件处理函数需要定义在Vue实例的methods中
const vm = new Vue({
el: "#app",
methods: {
btnClickHandler(arg){
// alert("点你咋地!!")
alert(arg);
},
divMouseEnterHandler(){
console.log("我进来了")
}
}
})
事件对象
-
如果在注册事件的时候,直接赋值的是函数的名字,不带小括号,那么vue会自动将事件对象传递给这个事件处理函数
<input type="text" @keyup="keyupHandler"> <!-- 可以如下调用事件对象,直接通过形参就可以使用了 --> const vm = new Vue({ el: "#app", methods: { keyupHandler(e){ console.log(e) } } })
-
如果在注册时间的时候,使用的是带有小括号的形式,则要获取事件对象,需要手动的传递参数$event
<input type="text" @keyup="keyupHandler($event)">
事件修饰符
<!--
使用方式
@事件名称.修饰符名称="事件处理函数"
-->
<div class="parent" @click="parentClickHandler">
<div class="child" @click.stop="childClickHandler"></div>
</div>
常用的事件修饰符
-
.stop
- 调用event.stopPropagation()
。 -
.prevent
- 调用event.preventDefault()
。 -
.capture
- 添加事件侦听器时使用 capture 模式。 -
.self
- 只当事件是从侦听器绑定的元素本身触发时才触发回调。 -
.once
- 只触发一次回调。事件修饰符是可以连写的
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为
v-on
在监听键盘事件时添加按键修饰符
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
还可以通过全局 config.keyCodes
对象自定义按键修饰符别名
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
v-model
在表单控件或者组件上创建双向绑定,你可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素
<!-- 当修改了input框中的数据,响应的Vue实例data中的对应数据也会修改 -->
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<input type="checkbox" id="checkbox" v-model="checked">
注:在文本区域插值 (
<textarea>{{text}}</textarea>
) 并不会生效,应用v-model
来代替。
v-model
在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用
value
属性和input
事件; - checkbox 和 radio 使用
checked
属性和change
事件; - select 字段将
value
作为 prop 并将change
作为事件。
v-pre指令
跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
<!-- 这样使用,则div及子元素都不会经过Vue的编译 -->
<!-- 可以提升性能-->
<div v-pre>
<p>111</p>
<p>111</p>
<p>111</p>
</div>
v-once指令
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
<!-- 都只会在第一次渲染的时候赋值,改变了值后,界面不会重新渲染-->
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 有子元素 -->
<div v-once>
<h1>comment</h1>
<p>{{msg}}</p>
</div>
Vue与ajax
-
用axios请求数据(推荐使用)
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
使用方式
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then( (response)=> { console.log(response); }) .catch( (error)=> { console.log(error); }); axios.get("/user").then((response)=>{}).catch(err => throw err) axios.请求方式(url [,{参数}]).then(response=>{}).catch(err=>{throw err})
axios 简写方式
axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }).then(response => { if(response.status == 200){ console.log(response.data); } })
注意:在then的回调函数中尽量使用箭头函数,因为如果使用function的话,在函数里使用this指向的时候,这个this指向的是window对象,而我们一般在获取的时候希望这个this是指向Vue的实例的,这样才可以在这个实例上添加数据
-
用vue-resource请求数据
返回的也是一个promise对象
使用方式
// 可以直接写在Vue实例的methods对象中 getInfo() { // get 方式获取数据 this.$http.get('http://127.0.0.1:8899/api/getlunbo').then(res => { console.log(res.body); }) } postInfo() { var url = 'http://127.0.0.1:8899/api/post'; // post 方法接收三个参数: // 参数1: 要请求的URL地址 // 参数2: 要发送的数据对象 // 参数3: 指定post提交的编码类型为 application/x-www-form-urlencoded this.$http.post(url, { name: 'zs' }, { emulateJSON: true }).then(res => { console.log(res.body); }); } jsonpInfo() { // JSONP形式从服务器获取数据 var url = 'http://127.0.0.1:8899/api/jsonp'; this.$http.jsonp(url).then(res => { console.log(res.body); }); }
-
RESTful 风格
接口的风格
一个URL地址就对应一个资源,对于资源不同的操作用请求方式来区分
传统接口的体现
http://xxxx.com/getallstudent
http://xxxx.com/addstudent
http://xxxx.com/deletestudent
http://xxxx.com/updatestudent
RESTFul 风格
http://xxxx.com/students get方式
http://xxxx.com/students/id get方式
http://xxxx.com/students/id delete方式
http://xxxx.com/studetns/id patch方式
Vue扩展
-
响应式数据
<div id="app"> <p> 我叫{{p.name}} <br> 我有辆{{p.car}} <br> 我今年才{{p.age}} </p> <button @click="btnAddAge">设置年龄</button> </div>
const vm = new Vue({ el: "#app", data: { p: { name: "zs", car: "玛莎拉蒂" } }, methods: { btnAddAge(){ // 给data中的对象动态新增的属性,不能够有响应式的效果,也就是说不能触发视图更新 // 如果想要有响应式效果 // 1. 就需要提前,在对象中先把属性声明好 在hcc中一开始就添加好age属性,哪怕不给值 // this.p.age = 18; // 2. 如果确实需要动态的给p对象添加age属性,那么我们可以用到vue中提供的$set方法 // 这个方法,可以动态的给数据添加响应式的属性! // this.$set(this.p, "age", 18); // Vue.set(vm.p, "age", 18) // 这两个方法是一样的 // 数组通过索引直接修改索引对应的内容,是无法实现响应式的效果 // this.students[1] = {id: 2, name: "ls"}; // 需要用set来设置 // this.$set(this.students, "1", {id: 2, name: "ls"}) } } });
什么时候用$set??
当给对象动态添加属性的时候,需要用$set
当想要通过数组的下表给元素赋值的时候,需要用$set
-
异步数据更新
Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更
如果你想基于更新后的 DOM 状态来做点什么,可以在数据变化之后立即使用 Vue.nextTick(callback)
这样回调函数将在 DOM 更新完成后被调用
<div id="example">{{message}}</div>
var vm = new Vue({
el: '#example',
data: {
message: '123'
}
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
vm.$el.textContent === 'new message' // true
})
// 也可以使用 vm.$nextTick
-
数据在vue实例上
我们是将数据放在参数对象中的data属性中传递给Vue构造函数的,Vue构造函数在接收到这个参数后
- 会读取data属性中所有的数据,通过Object.defineProperty方法,将这些数据全部加到vue实例上
- 这样做,可以让属性有了set和get方法,可以实现双向绑定等等功能
- 这样做,可以让程序员直接通过this来访问数据,方便使用
- Vue还会读取所有methods中的函数,把所有的函数,全部加给vue实例(可以通过this来访问这些函数)
更多推荐
所有评论(0)