VUE框架学习
昨天看了大概一半的内容,今天争取搞定所有VUE框架的入门知识
疑问:(已解决,在文末)
(今天只解决了第一个疑问,并且还遗留了一个小尾巴,官网给的代码里cb是个啥也不知道,剩下的四个问题遗留下来了,累了饿了以后效率太低,休息了)
1.关于watch的语法问题,昨天看到的教程是$watch,今天看到的是watch:{},没整明白这到底怎么用。
2.关于v-for里面key提升渲染效率?
3.对于v-for里面
<li v-for = "(item,index) of list" :key = "index">{{item}}</li>
对列表频繁变更时,这个存在问题?
5.Vue中emit的用法
学习内容
tip1:属性绑定
<div id ="root">
<div v-bind:title="title">hello world</div>
</div>
<script>
new Vue({
el:"#root",
data:{
title:"this is hello world"
}
})
</script>
v-bind就是属性绑定,那么这样,这里的v-bind:title="title"其实是一个表达式
v-bind:简写为:
tip2:双向数据绑定
<div id ="root">
<div v-bind:title="title">hello world</div>
<input v-model="content"/>
<div>{{content}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
title:"this is hello world"
content:"this is content"
}
})
</script>
v-bind是单方面的绑定,如果我们更改了data里面的title那么v-bind的绑定会随之改变,假如
<input v-model="content"/>
<div>{{content}}</div>
改成了
<input :value="content"/>
<div>{{content}}</div>
那么这里就没有了双向绑定,就只是实现了value值绑定content,content变了value也变化
但对于
<input v-model="content"/>
<div>{{content}}</div>
效果是整了个输入框,输入后改动了框内数据,完了content也跟着变了,这就是双向绑定
tip3:计算属性
<div id ="root">
<div v-bind:title="title">hello world</div>
<input v-model="firstname"/>
<input v-model="lastname"/>
<div>{{fullname}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstname:'',
lastname:''
},
computed:{
fullname: function(){
return this.firstname+' '+this.lastname
}
}
})
</script>
computed在这里表达的是计算属性,他是要缓存的,如果firstname和lastname没变,他就用上一次的缓存值,这也就是为什么说computed效率高一点,毕竟他是只有在发生改变后才真的去做。昨天的笔记中关于computed和methods区别的时候没能理解清楚,现在就很明了了,computed高效率,不想使用缓存那就不用computed
tip4:侦听
<div id ="root">
<div v-bind:title="title">hello world</div>
<input v-model="firstname"/>
<input v-model="lastname"/>
<div>{{fullname}}</div>
<div>{{count}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
firstname:'',
lastname:''
count:0
},
computed:{
fullname: function(){
return this.firstname+' '+this.lastname
}
},
watch:{
fullname:function(){
this.count ++
}
}
})
</script>
这里的fullname也可以换成firstname或者lastname都是可以的,它的作用就是监听数据变一次侦听到就把count++
tip5: v-if、v-show
<div id ="root">
<div v-if="show">hello world</div>
<button @click="handleClick">toggle</button>
</div>
<script>
new Vue({
el:"#root",
data:{
show:true
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
}
})
</script>
这个实现的功能就是click的时候改变show的属性值,如果他在显示就弄没,如果他没有就整一个出来。
<div id ="root">
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
</div>
<script>
new Vue({
el:"#root",
data:{
show:true
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
}
})
</script>
如果单看页面效果v-if和v-show是一样的,但是如果看控制台就会发现,show变成false后,v-if和v-show处理方式是不一样的,v-if做的是直接把标签
<div v-if="show">hello world</div>
弄没了,而v-show采取的做法是
<div style = "dispaly:none">hello world</div>
个人感觉其实区别真的不大,如果频繁消除又显示那肯定v-show好点,但是次数不多时候感觉也没啥差别。
tip6:v-for
没啥好说的,循环很简单
<div id ="root">
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
<ul>
<li v-for = "item of list">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el:"#root",
data:{
show:true
list:[1,2,3]
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
}
})
</script>
加个key值提升渲染效率,可以用每一项内容当key值,但是这个每一项item不能相同
<div id ="root">
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
<ul>
<li v-for = "item of list" :key = "item">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el:"#root",
data:{
show:true
list:[1,2,3]
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
}
})
</script>
有相同item可以加个index,当下标
<div id ="root">
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
<ul>
<li v-for = "(item,index) of list" :key = "index">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el:"#root",
data:{
show:true
list:[1,2,3]
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
}
})
</script>
tip7:push和提交后把框里内容清除
push就是把内容放进数组,下面一行是点了提交就清除框里的内容
tip8:组件
全局组件如下:
<ul>
<todo-item></todo-item>
</ul>
Vue.component('todo-item',{
template:'<li>item</li>'
})
局部组件:
局部组件要在对象里面声明出来,那个对象用就在哪里声明
这个components就是声明的地方
先对比一下上图内容和最初的全局组件有啥区别,会发现加了几行内容
<todo-item
v-for = "(item,index) of list"
:key = "index"
:content="item"
>
</todo-item>
props:['content'],
template:'<li>{{content}}</li>'
上图中做了这样一件事,想循环输出,框里加什么输出什么,那么我们就要用到v-for,为了输出的是随着输入来,那我们就不能用template:'<li>item</li>',
这里item写死了,所以我们用了一个{{content}},输入框里的东西给了content,就用的是:来绑定content和item
props:['content'],
这句话的作用是接收从外部传进来的参数,不然传不进来,那
template:'<li>{{content}}</li>'
想要输出content都没内容的。
tip9:组件和实例的关系
除了一个大的外层的实例(他的模板就是挂载点下面的所有内容),此外每一个vue的组件都是vue的实例,这样的话每个组件里面就有自己的template、props、data、method等等
tip10:实现todolist的删除功能(这部分逻辑比较绕)
这一部分要实现父组件和子组件的通信。
三个截图如下,观察其改动都在哪里
这里的改动在
:index="index"
@delete="handleDelete"
那么这里的index是为了给父组件传值,传过去一个下标帮助确认是哪一个要被delete,@就是:v-on的简写,是个监听,他在监听子组件delete参数,监听到了就执行handleDelete函数
这里的改动在于
1.props里面加了一个index,这就是获取到的下标
2.这个模板template里面有个@click他在监听click,监听到了就执行handleclick
3.增加的methods方法里面加了个handleClick函数,这个函数的作用是发出一个delete参数,携带了一个index值
这里的改动是加了handleDelete函数,点击会弹框,不过这个只是弹框,还没接收参数
这个是再一次改动后接收参数index,就是上面handleClick函数传出来的index,然后根据下标删除元素,输出的方法是把list里面的对应下标的元素splice掉,点一下只删一个所以第二个参数为1.
注:js的splice语法是:arrayObject.splice(index,howmany,item1,…,itemX)
参数 | 描述 |
---|---|
index | 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。 |
howmany | 必需。要删除的项目数量。如果设置为 0,则不会删除项目。 |
item1, …, itemX | 可选。向数组添加的新项目。 |
返回值
类型 | 描述 |
---|---|
Array | 包含被删除项目的新数组,如果有的话。 |
tip11:Vue-cli安装和配置
这个脚手架下载和配置就很费时间
https://www.imooc.com/video/16985全程跟着网课完成了安装
但是这个命令和网课有区别,官网改了教程:
npm install -g @vue/cli
安装完成后跟着网课用vue init webpack mydemo创建,这个就不详述,完成后会在桌面出现一个todolist文件夹,cd todolist 之后npm run dev
现在他会提醒已经启动在8080这个端口号上了。
之后任务就是在todolist文件夹里面编写。根据个人习惯我将文件夹放进了E盘用vscode打开,个人觉得vscode真的很适合写VUE
tip12:Vue-cli装好后了解一下todolist的目录结构
build和config目录下面都是些配置文件,包括项目配置和环境配置,先放着不动。
node_modules是项目的依赖
src指的是源代码放置的目录
static下面是静态资源
static下到index.html都不用动
index.html是整个web的html文件
整个项目里面入口在src目录下面的main.js文件
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
这里可以看到挂载点上是app
看main.js文件
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
import App from './App'
这一句是ES6的语法,是引入了一个局部组件。
疑问解决:
1.$watch在官网上的介绍是:观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。
先瞅一下这官方给的代码,说实话没看懂。
// 键路径
vm.$watch('a.b.c', function (newVal, oldVal) {
// 做点什么
})
// 函数
vm.$watch(
function () {
// 表达式 `this.a + this.b` 每次得出一个不同的结果时
// 处理函数都会被调用。
// 这就像监听一个未被定义的计算属性
return this.a + this.b
},
function (newVal, oldVal) {
// 做点什么
}
)
通过博客https://www.jianshu.com/p/7d202672aef6我提取到如下信息,总结了一下大概是这样:
$scope.$watch(watchObj,watchCallback,ifDeep)
这个就是语法,至于里面有啥,watchObj是监听的东西,包括某个数据、angular表达式,函数(检测函数返回值),以上都是字符串格式,并且都是在$scope
作用域下执行的。
watchObj变了就会调用watchAction(newValue,oldValue,scope)
1.newValue: watchObj的新的值;
2.oldValue: watchObj的旧的值;
3.scope: 就是当前控制器的$scope
;这个我看有的函数也没写,应该可以省略
注意:函数或者表达式不是在$scope
作用域下执行的,所以,如果是需要调用当前作用域下的某个函数,应该是scope.watchCallback
ifDeep:布尔值,是否深度监听。
ifDeep值设置为true, 那么angular会检测被监控对象的每个属性是否发生了变化。
比如说下面代码中,name和count都会被监听
$scope.$watch('data',function(){
},true)
$scope.data = {
name :'李四',
count:20
}
vm.$watch 返回一个取消观察函数,用来停止触发回调:
var unwatch = vm.$watch('a', cb)
// 之后取消观察
unwatch()
这个cb到底是啥我还没懂,完了具体操作的时候试一下。官网有点蠢。
2.key提升渲染效率,是因为VUE采取了就地复用,如果用key加了唯一的身份标识,那么在更改部分内容的时候就不用管未变更的。
3.key是唯一身份标示,如果key和下标对应,那么频繁变更时,如果经常在中间插入,就意味着插入位置后面的index都变了,就都得重新加载。如果每个部分里面都有个不同的id,让key对应id是最好的。
https://www.jianshu.com/p/342e2d587e69 比该博客对于2、3完美解释。
5.子组件可以使用 $emit 触发父组件的自定义事件。子组件@click后触发select事件,执行 $emit,触发父组件的updateCity事件
<template>
<div class="train-city">
<h3>父组件传给子组件的toCity:{{sendData}}</h3>
<br/><button @click='select(`大连`)'>点击此处将‘大连’发射给父组件</button>
</div>
</template>
<script>
export default {
name:'trainCity',
props:['sendData'], // 用来接收父组件传给子组件的数据
methods:{
select(val) {
let data = {
cityname: val
};
this.$emit('showCityName',data);//select事件触发后,自动触发showCityName事件
}
}
}
</script>
<template>
<div>
<div>父组件的toCity{{toCity}}</div>
<train-city @showCityName="updateCity" :sendData="toCity"></train-city>
</div>
<template>
<script>
import TrainCity from "./train-city";
export default {
name:'index',
components: {TrainCity},
data () {
return {
toCity:"北京"
}
},
methods:{
updateCity(data){//触发子组件城市选择-选择城市的事件
this.toCity = data.cityname;//改变了父组件的值
console.log('toCity:'+this.toCity)
}
}
}
</script>
今日任务:
VUE网课基本搞定,从语法到安装配置没啥问题了,但是VUE的难度和自己的效率自己没考虑好,今天看到了目录结构的部分看不动了。
明日任务:
学习VUE脚手架,做个小demo后,询问一下导师有没有什么学习路线,如果没有要求就准备一下mysql和spring boot,根据自己以往已经学过的进度,通过《spring boot in action》完成一下spring boot的自定义配置那一章。mysql没怎么用过,需要快点啃一下。