什么dom
(Document Object Model)
Dom分为3个类型
- 核心 DOM - 针对任何结构化文档的标准模型
- XML DOM - 针对 XML 文档的标准模型
- HTML DOM - 针对 HTML 文档的标准模型
HTML DOM
HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。
什么是vue.js的双向绑定
View是HTML显示界面
ViewModel是业务逻辑层
(一切js可视化业务逻辑,比如表单按钮提交,自定义事件的注册和处理逻辑都在viewmodel里面负责监控两边的数据)
Model数据层对数据的处理(比如增删改查)
MVVM是MODEL-VIEW-VIEWMODEL模型的缩写。MVVM是一种很设计模式。MODEL层代表数据模型,也可以在model中定义
数据修改和操作的业务逻辑;VIEW代表的是UI组件,它负责将数据模型转化为ui组件展示出来,VIEWModel是一个同步viewmodel的对象
在MVVM架构上,view和model并没有直接联系,而是通过viewmodel进行交互,model和viewmodel之间的交互是双向的,因此view的数据变化会同步到MODEL中,而MODEL数据的变化也会立即反应到view上
viewmodel通过双向数据绑定把view和model层连接起来,而view和model之间的同步工作完全是自动的,无需人为干涉。因此开发者只需要关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题,复杂的数据维护完全由MVVM来统一管理
条件与循环
<div id="app">
<p>{{message}}</p>
</div>
var app = new Vue({
el: '#app',
data: {
todos: [
{ text: '学习java'},
{ text: '学习Vue'},
{ text: '整个牛项目'}
]
}
})
处理用户信息
v-on
<div id="app">
<p>{{message}}</p>
<button v-on:click="reverseMessage"></button>
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function() {
this.message = this.message.split('').reverse().join("")
}
}
})
v-model
<div id="app">
<p>{{message}}</p>
<input v-model="message">
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
组件化应用实例
<div id="app">
<ol>
<!-- 创建一个 todo-item 组件的实例 -->
<todo-item></todo-item>
</ol>
</div>
Vue.component('todo-item', {
template: '<li>这是个待办项</li>'
})
var app = new Vue({
el: '#app'
})
v-bind
<div id="app">
<todo-item
v-for="item in groceryList"
v-bind:todo ='item'
v-bind:key = 'item.id'
>
</todo-item>
</div>
Vue.component("todo-item",{
props:["todo"],
template: "<li>{{todo.text}}</li>"
})
var app = new Vue({
el: "#app",
data: {
groceryList: [
{id: 1, text: '蔬菜'},
{id: 2, text: '猪肉'},
{id: 3, text: '牛肉'}
]
}
})
实例生命周期钩子
created
用来在一个实例被创建之后执行代码:
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
生命周期图示
模板语法
原始Html文件
<div id="app">
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using mustaches directive: <span v-html="rawHtml"></span></p>
</div>
var app = new Vue({
el: "#app",
data : {
rawHtml: '<span style="color: red">this is should be red</span>'
}
})
v-bind
<div id="app">
<div v-bind:class='color'>test</div>
</div>
var app = new Vue({
el: "#app",
data : {
color: 'red'
}
})
支持javascript表达式
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
只支持单个表达式 不支持下面的表达式
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
指令
指令 attribute 的值预期是单个 JavaScript 表达式
参数
如
<a v-bind:href="url">...</a>
又如
<a v-on:click="doSomething">...</a>
动态参数
<a v-bind:[attributeName]="url"> ... </a>
如果你的 Vue 实例有一个 data 属性 attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href。
修饰符
修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
<form v-on:submit.prevent="onSubmit">...</form>
缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
计算属性和侦听器
计算属性
基本用法
<div id="app">
<p>Original message: "{{message}}"</p>
<p>Computed Original message : "{{ reversedMessage}}"</p>
</div>
var app = new Vue({
el: "#app",
data: {
message: 'Hello'
},
computed:{
reversedMessage: function(){
return this.message.split('').reverse().join('')
}
}
})
计算属性vs方法
// 在组件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
侦听器
当采用异步操作或者开销更大的时候采用侦听器可以方便我的使用
Class和style绑定
绑定class
对象语法
<div
class="static"
v-bind:class="{ 'active': isActive, 'text-danger': hasError }"
></div>
var app = new Vue({
el: "#app",
data: {
isActive: true,
hasError: true
}
})
也可以这样绑定class样式
<div v-bind:class="classObject"></div>
var app = new Vue({
el: "#app",
data: {
classObject: {
'active': true,
'text-danger': false
}
}
})
通过数组语法进行命名
<div v-bind:class='[activeClass, errorClass]'></div>
var app = new Vue({
el: "#app",
data: {
activeClass: 'active',
errorClass: 'isLoading',
}
})
也可以应用在组件上
<my-component v-bind:class={active:isActive}></my-component>
Vue.component('my-component',{
template: '<p class="foo bar">Hi</p>'
})
var app = new Vue({
el: "#app",
data: {
isActive:true
}
})
绑定内联样式
对象语法
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
var app = new Vue({
el: "#app",
data: {
activeColor: 'red',
fontSize: 50
}
})
也可以这样写
<div v-bind:style= 'styleObject'>Hi</div>
var app = new Vue({
el: "#app",
data: {
styleObject: {
'color': 'red',
'font-size': '50px'
}
}
})
多重值
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
它会根据浏览器中渲染的最后一个数组来实现内容
条件渲染
v-if v-else
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
v-else-if
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
利用key管理可重复使用的元素
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
那么在上面的代码中切换 loginType 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input> 不会被替换掉——仅仅是替换了它的 placeholder
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key 属性即可:
v-if和v-show的区别
vif:
实时渲染:页面显示就渲染,不显示。我就给你移除
vshow:
vshow的元素永远存在也页面中,只是改变了css的display的属性
列表渲染
用v-for把一个数组对应一个元素
我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
<div id="app">
<li v-for="item in items" >
{{ item.message}}
</li>
</div>
var app = new Vue({
el: "#app",
data: {
items: [
{message: 'Foo'},
{message: 'Bar'}
]
}
})
也可以这样写
<div id="app">
<li v-for="(item,index) in items" >
{{parentMessage}}-{{index}}-{{ item.message}}
</li>
</div>
var app = new Vue({
el: "#app",
data: {
parentMessage: 'Parent',
items: [
{message: 'Foo'},
{message: 'Bar'}
]
}
})
在v-for里面使用对象
<div id="app">
<li v-for="value in Object" >
{{value}}
</li>
</div>
var app = new Vue({
el: "#app",
data: {
Object:{
title: 'Foo',
message: 'Bar'
}
}
})
也可以提供第二个参数键名还有第三个参数索引名字
<div id="app">
<li v-for="(value,name,index) in Object" >
{{index}}:{{name}}:{{value}}
</li>
</div>
var app = new Vue({
el: "#app",
data: {
Object:{
title: 'Foo',
message: 'Bar'
}
}
})
方法和事件
<div id="app">
点击次数: {{count}}
<button @click='handle()'>点我每次加一</button>
<button @click='handle(8)'>点我每次加8</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
count: 0
},
methods: {
handle: function (count) {
// console.log(count)
count = count || 1;
this.count += count;
}
}
})
</script>
如果方法中带有参数,但是你没有加括号,默认传原生事件对象event
vue.js 的修饰符号
在vue中传入event对象用 $event
向上冒泡
stop:阻止单击事件向上冒泡
prevent::提交事件并且不重载页面
self:只是作用在元素本身而非子元素的时候调用
once: 只执行一次的方法
可以监听键盘事件:
<input @keyup.13 ="submitMe"> ——指定的keyCode
vueJS为我们提供了:
.enter
.tab
.delete
<div id="app">
<!-- 向上冒泡 -->
stop用法: <br>
<div @click.self='divclick' style="height: 100px;width: 100px;background-color: red;">
<button @click='btnclick'>点击</button>
</div>
<hr>
prevent的用法:
每次提交表单都会重载页面
<form action="" @submit.prevent='hangle'>
<button type='submit'>提交表单</button>
</form>
<hr>
once: <br>
<button @click='onceMethod'>执行无限次</button>
<button @click.once='onceMethod'>只执行一次</button>
<hr>
监听键盘事件:
<br>
<input @keyup.13='submitMe'> ---keyCode
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
count: 0
},
methods: {
divclick: function () {
alert('div被点击了')
},
btnclick: function () {
alert('button被点击了')
},
hangle: function () {
alert('我不重载,页面也不刷新了')
},
onceMethod: function () {
alert('执行一次method')
},
submitMe: function () {
alert('您按下了enter键')
}
}
})
</script>
表单输入绑定
文本input
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
new Vue({
el: '#app',
data: {
message: ''
}
})
多行文本textarea同理
复选框
单个复选框
单个复选框绑定布尔值
<input type="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
new Vue({
el: '#app',
data: {
checked: ''
}
})
单选框同理
<input type="radio" v-model="checked" value="John">
<label for="John">John</label>
<input type="radio" v-model="checked" value="Jack">
<label for="Jack">Jack</label>
<label for="checkbox">{{ checked }}</label>
new Vue({
el: '#app',
data: {
checked: []
}
})
选择框
<div id="app">
<select v-model="selected" >
<option >A</option>
<option >B</option>
<option >C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: '#app',
data: {
selected: ''
}
})
值绑定
复选框
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
<span>Selected: {{ toggle }}</span>
new Vue({
el: '#app',
data: {
toggle: ''
}
})
单选按钮
<div id="app">
<input type="radio" v-model="pick" v-bind:value="a">
{{pick}}
</div>
new Vue({
el: '#app',
data: {
pick: '',
a: 'a'
}
})
修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述)。你可以添加 lazy
修饰符,从而转为在 change
事件之后进行同步:
<input v-model.lazy="msg">
{{msg}}
.number
<input v-model.number="msg" type="number">
{{msg}}
new Vue({
el: '#app',
data: {
msg: ''
}
})
.trim
<input v-model.trim="msg">
{{msg}}
new Vue({
el: '#app',
data: {
msg: ''
}
})
显示过滤,排序后的结果
computed过滤器
<div id="app">
<li v-for="n in evenNumbers" >
{{n}}
</li>
</div>
data: {
Object: [ 1,2,3,4,5,]
},
computed: {
evenNumbers: function(){
return this.Object.filter(function(number){
return number % 2 === 0
})
}
}
事件处理
监听事件
<div id="app">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has benn clicked {{counter }} times</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0
}
})
也可以定义为一个事件来进行处理
<div id="app">
<button v-on:click="add">Add 1</button>
<p>The button above has benn clicked {{counter }} times</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
add: function(){
this.counter += 1
}
}
})
内联处理器的方法
<button v-on:click="say('hi')"> Say hi</button>
<button v-on:click="say('fuck')"> Say fuck</button>
new Vue({
el: '#app',
methods: {
say: function(message){
alert(message)
}
}
})
事件修饰符
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
按键修饰符
<input v-on:keyup.enter="submit">
组件基础
data必须是一个函数
data: funciton(){
return{
count:0
}
}
通过props向子组件传递数据
Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
利用v-bind来动态传递prop
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
单个根元素
<h3>{{ title }}</h3>
<div v-html="content"></div>
Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。需要这样修改根元素
<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
当需要的post越来越多的时候,这时候就需要重构组件了
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
v-bind:content="post.content"
v-bind:publishedAt="post.publishedAt"
v-bind:comments="post.comments"
></blog-post>
例如这样进行重构
<div id="app">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
:post="post"
></blog-post>
</div>
Vue.component('blog-post',{
props: ['post'],
template: `
<div>
<h3>{{post.id}}</h3>
<h3>{{post.title}}</h3>
</div>
`
})
new Vue({
el: '#app',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
父子组件通过props通信
事前准备
<div id="app"></div>
var Child = {
template:`
<div>我是子组件</div>
`
}
var Parent = {
components:{
Child
},
template:`
<div>
<div>我是父组件</div>
<child></child>
</div>
`
}
new Vue({
el:'#app',
components:{
Parent
},
template:`
<div>
<div>我是主页</div>
<parent></parent>
</div>
`
})