【Vue】一
Vue简介
el和data的两种写法
const v = new Vue({
el: '#root',
data: {
name: '123'
}
})
动态指定el容器
console.log(v)
setTimeout(()=>{
v.$mount('#root')
},1000)
函数式返回data
data: function() {
return {
name: '123'
}
}
而不能写成箭头函数,因为箭头函数没有this,下面输出为window而不是vue
data:()=> {
console.log(this)
return {
name: '123'
}
}
在对象中写明方法也可以简写为
data() {
console.log(this)
return {
name: '123'
}
}
MVVM模型
M:模型(Model):Data中的数据
V:视图(View):模板代码
VM:视图模型(ViewModel):Vue实例
数据代理
Object.defineProperty方法(对象,新增属性,value)
let number = 18
let person = {
name: 'hikaru',
sex: 'w',
// age: 30
}
Object.defineProperty(person, "age", {
value: number,
enumerable: true, //设置新增属性可以枚举,默认为false
writable: true, //设置新增属性可以被修改,默认为false
configurable: true //设置新增属性可以被删除,默认为false
})
// 两种遍历方法
for (let key in person) {
console.log(person[key])
}
console.log(Object.keys(person))
console.log(person)
get和set方法
Object.defineProperty(person, "age", {
// value: number,
enumerable: true, //设置新增属性可以枚举,默认为false
// writable: true, //设置新增属性可以被修改,默认为false
// configurable: true, //设置新增属性可以被删除,默认为false
get() {
return number
},
set(value) {
console.log(value)
}
})
get在当age被读取时,get函数(getter)就会被调用,且返回值就是age的值
set在当age被修改时,set函数(setter)就会被调用,且参数就是被修改的age值
get set方法与writable、configurable属性重复不能一起写
数据代理实现
通过一个对象实现对另一个对象的读写操作
Vue.config.productionTip = false
let obj1 = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2, 'x', {
get() {
return obj1.x
},
set(value) {
obj1.x = value
}
})
Vue中的数据代理:通过vm对象来代理data中的数据
vm(vue实体)将model中的data赋值给vm中的_data
数据代理: 将_data中所有的属性通过Object.defineProperty添加到vm中。
vm的data调用getter、setter方法时就会获取修改model中的data。
事件处理 v-on:xxx / @xxx
<div id="root">
<button v-on:click="getInfo1">Info1</button><br/>
<button @click="getInfo2($event, 66)">Info2</button><br/>
<a href="https://www.baidu.com" @click="changeTarget">baidu</a><br/>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: "#root",
methods: {
getInfo1() {
alert('info1')
},
getInfo2(event, number) {
console.log(number)
},
changeTarget(event) {
alert(event.target.href)
event.target.href += '/s?wd=vue'
}
},
})
</script>
只有data中的数据会被数据劫持代理,如果把method加入data也会被数据代理
Vue常用事件修饰符
1 prevent 阻止默认事件
js写法
new Vue({
el: "#root",
methods: {
getInfo1() {
alert('info1')
},
getInfo2(event, number) {
console.log(number)
},
changeTarget(e) {
alert(e.target.href)
e.preventDefault();
}
},
})
Vue写法:@click.prevent
<a href="https://www.baidu.com" @click.prevent="changeTarget">baidu</a><br/>
2 stop 阻止事件向上级冒泡
3 once 事件只触发一次
4 capture 使用事件的捕获模式
5 self 只有event.target是当前操作的元素时才触发事件
<div id="root" @click.prevent.self="getInfo">
<button @click.prevent="getInfo">getInfo</button>
</div>
冒泡到root的div时target仍是按钮
<button>getInfo</button>
6 passive 事件的默认行为立即执行,无需等待事件回调执行完毕
键盘事件
@keyup 在按键抬起的时候触发事件
@keydown 在按键按下的时候触发事件
常用按键别名
回车 Enter
删除 Delete
退出 Esc
空格 Spacce
换行 tab 需要配合keydown使用
上 up
下 down
左 left
右 right
<div id="root">
<input type="text" placeholder="输入字符回车后提示" @keyup.enter="getInfo">
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: "#root",
methods: {
getInfo(e) {
console.log(e.key + ', ' + e.keyCode)
}
}
})
</script>
e.key + ', ' + e.keyCode 获取键盘输入字符和字符编码
如回车 Enter 13
计算属性
1 使用插值语法实现
<div id="root">
姓:<input type="text" v-model="firstName" ><br/>
名:<input type="text" v-model="lastName"><br/>
姓名:{{firstName + lastName}}
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: "#root",
data: {
firstName: '张',
lastName: '三'
}
})
</script>
2 使用methods实现
<div id="root">
姓:<input type="text" v-model="firstName" ><br/>
名:<input type="text" v-model="lastName"><br/>
姓名:{{getFullName()}}
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: "#root",
data: {
firstName: '张',
lastName: '三'
},
methods: {
getFullName() {
return this.firstName.slice(0,3) + '-' + this.lastName;
}
}
})
</script>
使用有返回值的方法时必须加括号
3 计算属性 利用已经有的属性计算生成新属性
computed: {
fullName: {
get() {
return this.firstName.slice(0,3) + '-' + this.lastName;
},
set() {
}
}
}
底层使用的是Object.defineProperty,方法get在被计算的属性被修改、计算的属性读取时被调用
只有get方法的计算属性的简写形式
computed: {
fullName: function(){
return this.firstName.slice(0,3) + '-' + this.lastName;
}
}
监视属性
两种监视方法
①通过Vue实例化时的watch属性
watch: {
firstName: {
immediate: true,
handler(newValue, oldValue) {
console.log(newValue + '=>' + oldValue)
}
}
}
immediate表示在被监视属性初始化时就调用handler
handler方法在被监视属性被修改时就会被调用
②通过vm
vm.$watch('lastName', {
immediate: true,
handler(newValue, oldValue) {
console.log(newValue + oldValue)
}
})
''为正常写法,不加引号是简写
在只有handler时的简写形式
watch: {
firstName(newValue, oldValue) {
console.log(newValue + oldValue)
}
}
})
vm.$watch('lastName', function(newValue, oldValue){
console.log(newValue + oldValue)
})
深度监视
watch: {
firstName: {
immediate: true,
deep: true,
handler(newValue, oldValue) {
console.log(newValue + '=>' + oldValue)
}
}
}
深度监视在数据有多层结构时会监视所有的层结构数据,默认为false
与计算属性的比较 需求:延迟显示
watch: {
firstName(val) {
setTimeout(()=>{
this.fullName = val + this.lastName
},1000
)
},
lastName(val) {
setTimeout(()=>{
this.fullName = this.firstName + val
},1000
)
}
computer可以完成的功能,watch都能完成,反之则不然,如监视属性方便进行异步,而计算属性只能瞬时return
这里使用了箭头函数,但是函数中的this仍为vm,这是因为箭头函数没有自己的this,需要递归向上寻找this,而lastName为普通函数且其this为vm,故箭头函数中的this为vm
箭头函数与普通函数的使用原则
①被Vue管理的函数使用普通函数,这样this指向的是vm实例 或者 组件对象
②所有不被Vue管理的函数,使用箭头函数,这样this指向的是vm实例 或者 组件对象
如:定时器的回调函数、ajax的回调函数、Promise的回调函数等
class与stye的绑定 :class
<body>
<div id="root">
<div class="basic" :class="classes" @click="changeMood">
</div>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
classes: 'normal'
},
methods: {
changeMood() {
let choose = Math.floor(Math.random(2) * 3)
let moods = ['normal', 'happy', 'sad']
this.classes = moods[choose]
}
}
})
</script>
①字符串写法
②数组写法
new Vue({
el: '#root',
data: {
classArr: 'normal'
},
methods: {
changeMood() {
let choose = Math.floor(Math.random(2) * 3)
let moods = ['normal', 'happy', 'sad']
this.classArr = moods[choose]
}
}
})
③对象写法
data: {
classArr: 'normal',
classObj: {
happy: false,
sad: true
}
},
条件渲染 v-if v-show
v-show=""中的表达式为真时,会为元素添加 style="display: none"
v-if 会直接让元素消失
列表渲染 v-for
遍历数组
<div id="root">
<h2>人员列表</h2>
<ul v-for="(emp, index) in employeeList" :key="index">
<li>{{emp.name}}-{{emp.age}}</li>
</ul>
</div>
new Vue({
el: '#root',
data: {
employeeList:[
{id: '001', name: '张三', age: 18},
{id: '002', name: '李四', age: 28},
{id: '003', name: '王五', age: 19}
]
},
methods: {
}
})
遍历对象
<div id="root">
<h2>人员列表</h2>
<ul v-for="(val, key) in employeeList[0]">
<li>{{val}} - {{key}}</li>
</ul>
</div>
接收对象的两个值先是value然后再是key
key的工作原理 虚拟DOM对比算法
key设置的属性为遍历对象的唯一标识
代码:
<body>
<div id="root">
<h2>人员列表</h2>
<ul v-for="(emp, index) in employeeList" :key="index">
<li>{{index}} : {{emp.name}}-{{emp.age}} <input type="text"></li>
</ul>
<button @click="add">add</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
employeeList:[
{id: '001', name: '张三', age: 18},
{id: '002', name: '李四', age: 28},
{id: '003', name: '王五', age: 19}
]
},
methods: {
add() {
const e = {id: '004', name: '老六', age: 30}
this.employeeList.unshift(e)
}
}
})
</script>
出现的问题:
原因:
虚拟DOM对比算法,即是在数据发生变化的时候,生成的虚拟DOM会和原来的虚拟DOM依据key值进行比较,如果相同则直接复用原来的DOM结构,否则会生成新的DOM结构
如上图中,key为0的两个DOM比较,发现文本不同但是输入框相同(虚拟DOM不会考虑文本框内的内容),因此会生成新文本“老刘-30”,然后复用原来的输入框。
解决方法
①使用数据中的id作为key值
<ul v-for="(emp, index) in employeeList" :key="emp.id">
<li>{{index}} : {{emp.name}}-{{emp.age}} <input type="text"></li>
</ul>
②或者使用不改变原有index顺序的插入方法
methods: {
add() {
const e = {id: '004', name: '老六', age: 30}
this.employeeList.push(e)
}
}
列表过滤
用watch实现
<body>
<div id="root">
<h2>人员列表</h2>
<input v-model="keyWord" placeholder="请输入信息"/>
<ul v-for="(person, index) in filPersons" :key="index">
<li>{{person.name}}-{{person.age}}</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
persons:[
{id: '001', name: '马冬梅', age: 18},
{id: '002', name: '周冬雨', age: 28},
{id: '003', name: '周杰伦', age: 19},
{id: '004', name: '温兆伦', age: 17}
],
filPersons: [],
keyWord: ''
},
methods: {
},
watch: {
keyWord: {
immediate: true,
handler(val) {
this.filPersons = this.persons.filter((p)=>{
return p.name.indexOf(val) !== -1;
})
}
}
}
})
</script>
使用计算属性
<body>
<div id="root">
<h2>人员列表</h2>
<input v-model="keyWord" placeholder="请输入信息"/>
<ul v-for="(person, index) in filPersons" :key="index">
<li>{{person.name}}-{{person.age}}</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
persons:[
{id: '001', name: '马冬梅', age: 18},
{id: '002', name: '周冬雨', age: 28},
{id: '003', name: '周杰伦', age: 19},
{id: '004', name: '温兆伦', age: 17}
],
keyWord: ''
},
methods: {
},
computed: {
filPersons() {
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1;
})
}
}
})
</script>
列表排序
computed: {
filPersons() {
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1;
})
if(this.sortType) {
arr.sort((p1, p2) => {
return this.sortType === 1 ? p1.age-p2.age : p2.age-p1.age
})
}
return arr
}
}
收集表单数据为JSON数据: JSON.stringify
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="./js/vue.js"> </script>
<style>
button {
margin-left: 2%;
}
</style>
</head>
<body>
<div id="root">
<form @submit.prevent="submit()">
<label for="userName">账号:</label>
<input type="text" id="userName" v-model="userInfo.userName"/><br/><br/>
<label for="password">密码:</label>
<input type="password" id="password" v-model="userInfo.password"/><br/><br/>
<label for="age">年龄:</label>
<input type="number" id="age" v-model.number="userInfo.age"/><br/><br/>
性别:
男<input type="radio" name="sex" value="male" v-model="userInfo.sex"/>
女<input type="radio" name="sex" value="female" v-model="userInfo.sex"/><br/><br/>
爱好:
学习<input type="checkbox" value="learning" v-model="userInfo.hobby">
打游戏<input type="checkbox" value="game" v-model="userInfo.hobby">
吃饭<input type="checkbox" value="eating" v-model="userInfo.hobby">
<br/><br/>
所属校区
<select v-model="userInfo.school">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
</select>
<br/><br/>
其他信息
<textarea v-model="userInfo.otherText">
</textarea><br/><br/>
<input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="#">《用户协议》</a>
<br/><br/>
<button type="submit">提交</button>
</form>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: '#root',
data: {
userInfo: {
userName: '',
passWord: '',
age: '',
sex: 'male',
hobby: [],
school: '',
otherText: '',
agree: true
}
},
methods: {
submit() {
console.log(JSON.stringify(this.userInfo))
}
},
computed: {
}
})
</script>
</html>
【Vue】一的更多相关文章
- Vue.js 和 MVVM 小细节
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
- Vue + Webpack + Vue-loader 系列教程(2)相关配置篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ 使用预处理器 在 Webpack 中,所有的预处理器需要和一个相应的加载器一同使用.vue- ...
- Vue + Webpack + Vue-loader 系列教程(1)功能介绍篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue-loader 是一个加载器,能把如下格式的 Vue ...
- 关于Vue.js 2.0 的 Vuex 2.0,你需要更新的知识库
应用结构 实际上,Vuex 在怎么组织你的代码结构上面没有任何限制,相反,它强制规定了一系列高级的原则: 应用级的状态集中放在 store 中. 改变状态的唯一方式是提交mutations,这是个同步 ...
- Vue.js 2.0 和 React、Augular等其他框架的全方位对比
引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那么你就来对了. 客观来说,作为核心团队成员,显然我们会 ...
- 窥探Vue.js 2.0 - Virtual DOM到底是个什么鬼?
引言 你可能听说在Vue.js 2.0已经发布,并且在其中新添加如了一些新功能.其中一个功能就是"Virtual DOM". Virtual DOM是什么 在之前,React和Em ...
- 初探Vue
Vue.js(读音/vju:/,类似于view),是近来比较火的前端框架,但一直没有怎么具体了解.实现过,就知道个啥的MVVM啦,数据驱动啦,等这些关于Vue的虚概念. 由于最近,小生在公司中,负责开 ...
随机推荐
- The first blog
这是一只爱碎觉的汪的第一篇博客. 下面就来简单介绍一下自己吧,爱好广泛,尤其热爱钢琴和运动,喜欢每个按键在手指间跳动的感觉,喜欢一个个音符连起来奏响的一曲曲优美的音乐,也喜欢运动后大汗淋漓的畅快感.肯 ...
- logging 模块详解
日志记录函数以它们用来跟踪的事件的级别或严重性命名.下面描述了标准级别及其适用性(从高到低的顺序) 日志等级(level) 描述DEBUG 最详细的日志信息,典型应用场景是 问题诊断INFO 信息详细 ...
- virtualvm2 观察者模式
<template> <div id="app"> <input type="text" v-model='msg'> &l ...
- js 遍历对象属性
function* objectEntries(obj) { let propKeys = Reflect.ownKeys(obj); for (let propKey of propKeys) { ...
- 【再学WPF】模板
1 <!--设置所有的按钮样式--> 2 <Style TargetType="Button"> 3 <Setter Property="M ...
- MapReduce实践
1. 词频统计任务要求 首先,在Linux系统本地创建两个文件,即文件wordfile1.txt和wordfile2.txt.在实际应用中,这两个文件可能会非常大,会被分布存储到多个节点上.但是,为了 ...
- C++ || const_cast 将const变量转为非const
点击查看代码 #include <iostream> using namespace std; int main() { int a =5; const int* p=&a;//需 ...
- PYQT搭建相关记录
class Demo(QWidget): def __init__(self): super(Demo, self).__init__() # 设置标题 icon 尺寸 self.setWindowT ...
- NX二次开发获取当前DLL路径函数
string GetPath();//输出程序路径 string YiNingToolPath(string DLLDir); //分割程序路径获取工具目录 HMODULE GetSelfModule ...
- 网络安全(中职组)-B模块:Web安全应用-2
Web安全应用-2 任务环境说明: √ 服务器场景: match_win03-3-1(关闭链接) √ 服务器场景操作系统:Windows Server 2003 1. 使用渗透机Kali Linux, ...