Vue随记
本文不是vue的系统性学习,只是基础部分的快速上手(本文以Vue2为例)
引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
声明式渲染
看一个简单的案例
<body>
<div id="app" v-bind:title="title">
{{message}}
</div>
<script>
var app = new Vue({
el: '#app',
data:{
message:'hello vue!',
title:'dzr'
}
})
</script>
</body>
使用vue
之后我们不再和 HTML
直接交互了,一个 Vue 应用会将其挂载到一个 DOM 元素上 (对于这个例子是 #app
) 然后对其进行完全控制
v-bind
attribute 被称为指令。指令带有前缀 v-
,以表示它们是 Vue 提供的特殊 attribute
条件指令
这个案例里v-if中flag若为true则显示div内容
<body>
<div id="app">
<div v-if="flag">hello dzr</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
flag:true
}
})
</script>
</body>
如果是v-show则是通过css样式来隐藏
如果频繁隐藏显示建议使用v-show
<div v-show="flag">hello dzr</div>
循环指令
下面是一个乘法表,在控制台可以通过修改app.num来更换乘法表行列数
<body>
<div id="app">
<table border="1">
<tr v-for="i in num">
<td v-for="j in i">{{j}}*{{i}}={{j*i}}</td>
</tr>
</table>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
num:9
}
})
</script>
</body>
处理用户输入
事件监听
用v-on
指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法
<body>
<div id="app">
<div>{{message}}</div>
<button v-on:click="reverseMessage">翻转消息</button>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
message:'hello,dzr!'
},
methods:{
reverseMessage(){
this.message = this.message.split('').reverse().join('')
}
}
})
</script>
</body>
双向绑定
v-model
指令能实现表单输入和应用状态之间的双向绑定
<body>
<div id="app">
<div>{{message}}</div>
<input type="text" v-model="message">
</div>
<script>
var app = new Vue({
el:"#app",
data:{
message:'hello,dzr!'
}
})
</script>
</body>
组件
一个组件本质上是一个拥有预定义选项的一个 Vue 实例
<body>
<div id="app">
<dzr v-bind:name="dzr"></dzr>
</div>
<script>
Vue.component("dzr",{
props:['name'],
template:'<h1>hello,{{name}}!</h1>'
})
var app = new Vue({
el:"#app",
data:{
message:'hello,dzr!',
dzr:"正如"
}
})
</script>
</body>
实例
当一个 Vue 实例被创建时,它将 data
对象中的所有的 property
加入到 Vue 的响应式系统中
当这些 property
的值发生改变时,视图将会产生“响应”,即匹配更新为新的值
值得注意的是只有当实例被创建时就已经存在于 data
中的 property
才是响应式的,即后面创建的不响应
使用 Object.freeze()
,这会阻止修改现有的 property
,也就是响应系统无法再追踪变化
created
钩子可以用来在一个实例被创建之后执行代码,也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted
、updated
和 destroyed
。生命周期钩子的 this
上下文指向调用它的 Vue 实例。
<body>
<div id="app">
<div>{{a}}</div>
</div>
<script>
var data = {a:1}
Object.freeze(data)
var app = new Vue({
el:"#app",
data:data,
created (){
console.log("vue create")
}
})
console.log(data.a == app.a)
data.a = 99
console.log(app.a)
console.log("<<<<<<<<<<<<<<<<<<<<<<<")
console.log(app.$el == document.getElementById("app")) // => true
console.log(app.$data == data) // => true
</script>
</body>
模板
v-once
指令,可以执行一次性地插值,当数据改变时,插值处的内容不会更新
v-html
指令,可以输出真正的HTML
v-bind
指令,让语法能够作用在 HTML attribute 上
值得注意的是{{ }}
中流控制不会生效,请使用三元表达式
<body>
<div id="app">
<div>{{a}}</div>
<button v-bind:disabled="!enableBtn" v-on:click="num++">按钮</button>
<div v-html="a"></div>
<div>{{num>101?"good":num}}</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
a:"<h1>Hello,DZR</h1>",
b:null,
enableBtn:true,
num:99
}
})
</script>
</body>
计算属性
与方法相比,计算属性有缓存,比如下面如果message没有变化,则会调用缓存
下面的计算属性的set方法是当app.reverseMessage发生变化时会调用
<body>
<div id="app">
<div>{{reverseMessage}}</div>
<!-- <div>{{reverseMessage()}}</div>-->
</div>
<script>
var app = new Vue({
el:"#app",
data:{
message:'hello,dzr!'
},
computed:{
reverseMessage:{
get(){
return this.message.split('').reverse().join('')
},
set(newValue){
console.log("set:"+newValue)
}
}
// reverseMessage(){
// return this.message.split('').reverse().join('')
// }
},
// methods:{
// reverseMessage(){
// return this.message.split('').reverse().join('')
// }
// }
})
</script>
</body>
侦听器
这里侦听了firstName
和lastName
,当他们发生变化时会更新fullName
,在这里使用watch
是为了演示侦听器的用法,实际中一些复杂的异步才会使用watch
,否则使用计算属性computed
即可
<body>
<div id="app">
<div>{{fullName}}</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
firstName:'zhang',
lastName:'san',
fullName:'zhang san'
},
watch:{
firstName(val){
this.fullName = val + " " + this.lastName
},
lastName(val){
this.fullName =this.firstName + " " + val
}
}
})
</script>
</body>
Class绑定
动态和静态可以共存,放flag
为true
时,mydiv
会生效,动态也可以有多个,也可以创建一个对象如下面的classObj
<body>
<div id="app">
<div v-bind:class="{mydiv:flag,mydiv2:flag}" class="mydiv1">{{msg}}</div>
<div v-bind:class="classObj" class="mydiv1">{{msg}}</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "hello,dzr!",
flag: true,
classObj:{
mydiv:true,
mydiv2:true
}
}
})
</script>
<style>
.mydiv2{
border: 1px solid;
}
.mydiv1{
font-size: 30px;
}
.mydiv{
font-weight: bold;
color: #ff0000;
}
</style>
</body>
Style绑定
跟上面的差不多
条件渲染
- 想用
v-if
切换多个元素可以把一个<template>
元素当做不可见的包裹元素,并在上面使用v-if
,最终的渲染结果将不包含<template>
元素,另外v-else
元素必须紧跟在带v-if
或者v-else-if
的元素的后面,否则它将不会被识别 - 一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好 - 不推荐同时使用
v-if
和v-for
,当v-if
与v-for
一起使用时,v-for
具有比v-if
更高的优先级
列表渲染
<body>
<div id="app">
<table border="1px">
<tr>
<td>序号</td>
<td>书名</td>
<td>作者</td>
</tr>
<tr v-for="(book,index) in books" v-bind:key="index">
<td>{{index+100 }}</td>
<td>{{book.name}}</td>
<td>{{book.author}}</td>
</tr>
</table>
<hr>
<div v-for="(s,p,index) in site" v-bind:key="index">{{s}}--{{p}}--{{index}}</div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
books:[
{
name:"三国演义",
author:"罗贯中"
},{
name:"红楼梦",
author:"曹雪芹"
},{
name:"水浒传",
author:"施耐庵"
},{
name:"西游记",
author:"吴承恩"
},
],
site:{
author:"dzr",
url:"zhengru.top",
server:"Tencent"
}
}
})
</script>
</body>
数组更新检测
变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
比如上面的例子就可以通过app.books.push({name:"123",author:"456"}) 5
来更新数组
替换数组
变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()
、concat()
和 slice()
。它们不会变更原始数组,而总是返回一个新数组
上面的例子可以通过app.books=app.books.concat({name:"456",author:"789"})
添加一组数据
从第0个开始删除1个并添加一组数据app.books.splice(0,1,{name:"abc",author:"def"})
Vue.set(app.site,"ip","0.0.0.0")
事件处理
v-on
前面已经提到过了,可以在methods
里定义方法再去调用
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
按键码
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
表单输入绑定
文本
<input type="text" v-model="message">
<div>{{message}}</div>
多行文本
<textarea v-model="textarea" name="" id="" cols="30" rows="10"></textarea>
<p style="white-space: pre-line;">{{textarea}}</p>
复选框
<input type="checkbox" value="唱" v-model="favourites">
<input type="checkbox" value="跳" v-model="favourites">
<input type="checkbox" value="Rap" v-model="favourites">
<input type="checkbox" value="篮球" v-model="favourites">
<div>{{favourites}}</div>
单选按钮
<input type="radio" value="男" v-model="gender">男
<input type="radio" value="女" v-model="gender">女
<div>{{gender}}</div>
选择框
学历:
<select v-model="edu">
<option value="小学">小学</option>
<option value="初中">初中</option>
<option value="高中">高中</option>
</select>
<div>{{edu}}</div>
多选框
<select v-model="favourite2" multiple>
<option value="唱">唱</option>
<option value="跳">跳</option>
<option value="Rap">Rap</option>
<option value="篮球">篮球</option>
</select>
<div>{{favourite2}}</div>
修饰符
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步
你可以添加 lazy
修饰符,从而转为在 change
事件之后进行同步
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符
组件基础
// 定义一个名为dzr的新组件
Vue.component('dzr', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
组件复用
data必须是一个函数
data: function () {
return {
count: 0
}
}
通过Prop向子组件传递数据
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
单个根元素
可以将模板的内容包裹在一个父元素内,来修复这个问题
监听子组件事件
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
使用事件抛出一个值
可以使用 $emit
的第二个参数来提供这个值
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>
插槽
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
动态组件
在下面的示例中,currentTabComponent
可以包括
- 已注册组件的名字
- 一个组件的选项对象
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
到这里简单入了个门,其他的等后续再慢慢补充…
基本环境搭建
安装NodeJS和npm后在cmd中运行
npm install -g vue-cli # 只需要第一次安装时执行
npm install -g @vue-cli@3.11.0 # 指定版本
vue init webpack my-project # 使用webpack模板创建一个vue项目
cd my-project #进入到项目目录中
npm install # 下载依赖(如果在项目创建的最后一步选择了自动执行npm install,则该步骤可以省略)
npm run dev # 启动项目