Vue--基础1
vue
vue是一个轻量级的前端框架,渐进式javascript框架,它是当下国内很火的一个javascript mvvm库,它是以数据驱动和组件化的思想构建的。
相比较于jquery的dom操作,vue是数据驱动的,不需要再通过获取标签对象在进行操作。通过一些特殊的语法,把dom和数据绑定在一起,一旦你创建了绑定,dom将和数据保持同步,每当数据发生变化,dom也会相应的更新。
vue管理页面很强大,它可以控制一个页面的一个标签,也可以控制一个页面,甚至控制一个项目,我们只需要把一个项目的页面一次性传到前台,不需要的可以先保存在客户端的内存缓存中,当需要的时候在进行加载
vue的优点
- 综合了angular和react的优点,上手快(一手文档是中文),完全开源免费
- 单页面的web运用,服务于移动端,只需要向后台请求数据就可以了
- mvvm设计模式
- 数据驱动,在缓存中根据数据处理dom,再渲染给真实dom
- 页面缓存机制--虚拟dom
- 数据的双向绑定
mvvm模式
mvvm------model-view-viewmodel
下图描述了vue中viewmodel是如何和view以及model进行交互的。
viewmodel是vue.js的核心,它是一个vue实例。vue实例是作用于某一个html元素上的,这个元素可以是html的body元素,也可以是指定了id的某个元素。
当创建了viewmodel后,双向绑定是如何达成的呢?
首先,我们将上图中的dom listeners和data bindings看作两个工具,它们是实现双向绑定的关键。
从view侧看,viewmodel中的dom listeners工具会帮我们监测页面上dom元素的变化,如果有变化,则更改model中的数据;
从model侧看,当我们更新model中的数据时,data bindings工具会帮我们更新页面中的dom元素。
hello world示例
<!doctype html> <html> <head> <meta charset="utf-8"> <title>hello world示例</title> </head> <body> <!--这是我们的view--> <div id="app"> {{ message }} </div> </body> <script src="js/vue.js"></script> <script> // 这是我们的model var exampledata = { message: 'hello world!' } // 创建一个 vue 实例或 "viewmodel" // 它连接 view 与 model new vue({ el: '#app', data: exampledata }) </script> </html>
使用vue的过程就是定义mvvm各个组成部分的过程的过程
- 定义view
- 定义model
- 创建一个vue(viewmodel)实例,用于连接view和model
挂载点
在上述示例中,通过挂载点进行vue实例绑定,进行了页面绑定
选项对象的el属性指向view,el:"#app"
表示该vue实例挂载到<div id="app">...</div>
这个元素,data属性指向model,data: exampledata
表示我们的model是exampledata对象。
vue挂载点的注意事项:
- 挂载点只遍历第一个匹配的结果
- html与body标签不可以作为挂载点
- 挂载点的只一般就采用id选择器(唯一性)
插值表达式与过滤器
在vue中有很多种数据绑定方式,最基础的形式是文本插值,使用一对{{ }}
包裹变量,如运行{{ message }}
会被数据对象的message属性替换,所以页面会输出hello world!
<div id="app"> <!-- 插值表达式 --> <!-- 可以进行数据处理 --> <h1>{{ msg.split('')[0] }}</h1> <h2>{{ info + msg }}</h2> <h3>{{ num * num }}</h3> <!--num作为过滤器的参数,过滤器的返回值就是表达式的值--> <h4>{{ num | my_filter }}</h4> <!--过滤器f1被传递了四个参数a,b,c,d,并将过滤结果做出f2的参数再过滤--> <h4>{{ a, b | f1(c, d) | f2 }}</h4> <h4>{{ arr | f3 }}</h4> </div> <script src="js/vue.js"></script> <script> // 创建过滤器 vue.filter('my_filter', function (v) { console.log(v); return 999 }); vue.filter('f1', function (a, b, c, d) { console.log(a, b, c, d); // return '过滤后的逻辑结果' return a + b + c + d }); vue.filter('f2', function (v) { console.log(v); return v * v }); vue.filter('f3', function (v) { let new_arr = []; for (n of v) { if (n >= 60) { new_arr.push(n) } } return new_arr }); // 产生vue实例对象 new vue({ el: '#app', // data成员用来为vue控制的变量提供值 data: { msg: 'message', info: '信息', num: 10, a: 1, b: 2, c: 3, d: 4, arr: [23, 59, 62, 97] } }) </script>
vue指令
- 文本指令
- 属性指令
- 事件指令
- 表单指令
- 条件指令
文本指令
格式:
-
{{ 变量表达式 }}
:渲染变量 -
v-text='变量表达式'
:渲染变量 -
v-html='html标签'
:渲染可被解析的html标签 -
v-once='被限制的变量'
:内容还是通过上面三种进行渲染, 如果内容中包括被限制的变量
,则渲染后的内容不会发生变化
<div id="app"> <!-- 文本指令 --> <h2 v-text="msg + '!!!'"></h2> <h2 v-text="htm"></h2> <h2 v-html="htm"></h2> <input type="text" v-model="msg"> <h3>{{ msg }}</h3> <!--一次性渲染,插值表达式中的任何一个变量被限制,整个结果就不可变--> <h3 v-once="htm">{{ msg + htm }}</h3> <!-- 只要有v-once,这个标签渲染完成后就不会发生变化 --> <h3 v-once>{{ msg }}</h3> </div> <script src="js/vue.js"></script> <script> new vue({ el: '#app', data: { msg: 'message', htm: '<i>标签内容是否被解析</i>' } }) </script>
属性指令
格式:v-bind:属性名='属性值'
,可以简写成 :属性名='属性值'
<!doctype html> <html> <head> <meta charset="utf-8"> <title>属性指令 - 控制样式</title> <style> .div { width: 200px; height: 200px; background-color: red; } .box { width: 200px; height: 200px; } .blue { background-color: blue; } .green { background-color: green; } </style> </head> <body> <div id="app"> <div class="div" style="border-radius: 50%"></div> <!--属性指令:v-bind:属性名="属性值" => v-bind: 可以简写为 : eg: v-bind:style="{color: 'red'}" --> <!--自定义属性:没有太多应用场景--> <!--只是普通的自定义属性--> <div abc="xyz"></div> <!-- 通过vue进行变量替换 --> <div v-bind:abc="xyz"></div> <!--title属性--> <div :title="xyz" class="div" style="border-radius: 50%"></div> <!--style属性--> <!--1)变量:变量的值为字典--> <div :style="my_style"></div> <!--2)字典中的多个变量--> <div :style="{width: w, height: h, background: b}"></div> <!--class属性--> <!--<div class="box blue"></div>--> <div :class="c"></div> <div :class="[c1, c2]"></div> <div :class="[c1, 'blue']"></div> <!--x为类名,是否生效有变量y(true|false)值决定--> <!-- x只能是类名,不可以通过data进行变量替换 --> <div :class="{x: y}"></div> <div :class="[{'box': true}, c2]"></div> </div> </body> <script src="js/vue.js"></script> <script> new vue({ el: '#app', data: { xyz: 'abc', my_style: { width: '100px', height: '100px', 'background-color': 'cyan', borderradius: '50%' }, w: '50px', h: '50px', b: 'red', c: 'box blue', c1: 'box', c2: 'green', y: true, } }) </script> </html>
事件指令
格式:v-on:指令="fn变量"
,可以简写成 @指令="fn变量"
<!doctype html> <html> <head> <meta charset="utf-8"> <title>事件指令</title> <style> .div1 { width: 200px; height: 200px; background-color: red; } /*没有vue,不显示,有vue,会移除该属性 => 没有闪烁的显示内容*/ [v-cloak] { display: none; } div { width: 50px; height: 50px; background-color: red; border-radius: 50%; text-align: center; line-height: 50px; color: white; cursor: pointer; } </style> </head> <body> <div id="app" v-cloak> <!--事件指令 v-on:事件名="fn变量" => v-on: 可以简写为 @ v-on:click="clickaction" @dblclick="dblclickaction" --> <!--内容操作:每点一次,内容+1--> <h2 v-once="num">{{ num }}</h2> <h2>{{ num }}</h2> <div v-on:click="clickaction" class="div1">{{ num }}</div> <hr> <!--样式操作:点击切换背景颜色--> <div @click="changecolor" class="div1" :style="{backgroundcolor: bgcolor}"></div> <!--样式操作:点击切换整体样式--> <div @click="changestyle" :style="my_style"></div> <!--没有传值默认传 事件对象 --> <div @click="btnclick1">{{ msg }}</div> <!--方法()不会直接调用方法,而是在点击触发后进行传参,接收到的参数就是传入的参数--> <div @click="btnclick2(1, msg)">{{ msg }}</div> <!--一旦书写 方法() 就不再传入事件对象,通过 $event 手动传入事件对象--> <div @click="btnclick3(msg, $event, $event)">{{ msg }}</div> </div> </body> <script src="js/vue.js"></script> <script> let app = new vue({ el: '#app', data: { num: 100, bgcolor: 'cyan', my_style: { width: '100px', height: '100px', backgroundcolor: 'orange' }, msg: 'box' }, methods: { clickaction: function () { // console.log(app.num); // console.log(this.num); this.num ++ }, changecolor () { // 方法的写法 // if (this.bgcolor == 'cyan') { // this.bgcolor = 'blue' // } else { // this.bgcolor = 'cyan' // } // python:this.bgcolor = 'cyan' if this.bgcolor != 'cyan' else 'blue' this.bgcolor = this.bgcolor != 'cyan' ? 'cyan' : 'blue' }, changestyle: () => { // 这种写法,内部拿不到this(指向的是window) app.my_style = app.my_style.backgroundcolor == 'orange' ? { width: '200px', height: '200px', backgroundcolor: 'yellow' } : { width: '100px', height: '100px', backgroundcolor: 'orange' } }, btnclick1(ev) { console.log(ev); console.log(ev.clientx); }, btnclick2(a, b, c) { console.log(a, b, c) }, btnclick3(a, b, c) { console.log(a, b, c) }, } }); // 外界访问实例内部的数据 console.log(app); console.log(app.$el); console.log(app.$data.num); console.log(app.num); </script> </html>
表单指令
格式:v-model="变量"
:无简写方式
<!doctype html> <html> <head> <meta charset="utf-8"> <title>表单指令</title> </head> <body> <div id="app"> <form action=""> <!--表单指令:v-model="变量"--> <!--双向绑定:一个地方修改值,所有地方的数据都会被更新--> <div> <input type="text" v-model="info" name="usr"> <input type="password" v-model="info" name="pwd"> <p>{{ info | infofilter }}</p> </div> <div> <!--单选框:v-model="变量存放的是某个单选框的value值,代表该选框选中"--> 男<input type="radio" name="sex" value="male" v-model="sex_val"> 女<input type="radio" name="sex" value="female" v-model="sex_val"> </div> <div> <!--单独的复选框:v-model="true|false代表该选框是否选中"--> 是否同意<input v-model="cb_val" value="yes" type="checkbox" name="agree"> </div> <div> <!--群复选框:v-model="存放选中选框value的数组"--> 男<input v-model="cbs_val" value="male" type="checkbox" name="hobby"> 女<input v-model="cbs_val" value="female" type="checkbox" name="hobby"> 哇塞<input v-model="cbs_val" value="others" type="checkbox" name="hobby"> <p>{{ cbs_val }}</p> </div> <div> <input type="submit"> </div> </form> </div> </body> <script src="js/vue.js"></script> <script> vue.filter('infofilter', (info) => { return info ? info : '初始内容' }); new vue({ el: '#app', data: { info: '', // 默认值可以决定单选框默认选项 sex_val: 'female', // 默认值为true,单一复选框为选中,反之false为不选中 cb_val: 0, // 数组中存在的值对应的复选框默认为选中状态 cbs_val: ["others"] } }) </script> </html>
条件指令
格式:
-
v-if="true|false"
:条件为true
时显示内容,且屏蔽下方分支为false
时隐藏不渲染到页面 -
v-else-if="true|false"
:v-if
不成立时才看v-else-if
、v-else-if
成立会屏蔽下方分支 -
v-else="true|false"
:v-if
、v-else-if
都不成立,v-else
才成立 -
v-show="true|false"
:条件为true
时显示内容,为false
时隐藏渲染到页面,但是display:none
<!doctype html> <html> <head> <meta charset="utf-8"> <title></title> <style> .btn1 { width: 400px; } .box { width: 200px; height: 200px; float: left; } .wrap:after { content: ''; display: block; clear: both; } .red { background-color: red } .blue { background-color: blue } </style> <style> .btn-wrap { height: 25px } .btn { width: 100px; height: 25px; float: left; } .page { width: 300px; height: 150px; } .p1 { background-color: pink } .p2 { background-color: yellow } .p3 { background-color: green } </style> </head> <body> <div id="app"> <!--条件指令 v-if="true|false" v-show="true|false" --> <button class="btn1" @click="btnclick">{{ title }}</button> <div class="wrap"> <!--v-if隐藏时不渲染,v-show隐藏时用display:none渲染--> <!--v-if隐藏时在内存中建立缓存,可以通过key属性设置缓存的键--> <div class="box red" v-if="is_show" key="box_red"></div> <div class="box blue" v-show="is_show"></div> </div> <div class="btn-wrap"> <button class="btn" @click="changepage('pink')">粉</button> <button class="btn" @click="changepage('yellow')">黄</button> <button class="btn" @click="changepage('green')">绿</button> </div> <div> <!--v-if成立会屏蔽下方分支、v-else-if一样f成立会屏蔽下方分支--> <!--v-if不成立时才看v-else-if、v-else-if成立会屏蔽下方分支--> <!--v-if、v-else-if都不成立,v-else才成立--> <div class="page p1" v-if="page == 'pink'"></div> <div class="page p2" v-else-if="page == 'yellow'"></div> <div class="page p3" v-else></div> </div> </div> </body> <script src="js/vue.js"></script> <script> new vue({ el: '#app', data: { title: '隐藏', is_show: true, page: localstorage.page || 'pink' }, methods: { btnclick() { this.title = this.title == '隐藏' ? '显示' : '隐藏'; this.is_show = !this.is_show; }, changepage(page) { this.page = page; localstorage.page = page; // 永久缓存 // sessionstorage.page = page; // 临时缓存 } } }) </script> </html>
上一篇: Javascript获取元素的xpath