vue的学习笔记
本笔记基于狂神说vue的视频,旨在加强自己的记忆,该笔记更新完成。
1、第一个Vue程序
步骤:
- 导入vue.js(方法很多,这里使用cdn的方式导入)
- 写Model
- 与前端绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
{{message}}
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message:"fuck vue"
}
})
</script>
</body>
</html>
2 MVVM
MVVM是Model-View-ViewModel的简写。它本质上就是MVC (Model-View- Controller)的改进版。即模型-视图-视图模型。【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。
用vue.js可以很好的实现MVVM。
3 Vue的语法
3.1 v-bind 绑定元素
格式v-bind:属性=“vue中对应的model”
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
3.2 v-if、v-else-if、v-else 条件渲染
<div id="app">
<h1 v-if="choice==='A'">A</h1>
<h1 v-else-if="choice==='B'">B</h1>
<h1 v-else-if="choice==='C'">C</h1>
<h1 v-else>D</h1>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
choice: 'A'
}
})
</script>
3.3 v-for列表渲染
<div id="app">
<li v-for="item in items">
{{item.message}}
</li>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
items:[
{message:"注解"},
{message:"反射"},
{message:"多线程"},
]
}
})
</script>
<div id="app">
这里还可以直接使用 {item,index} in items把索引下标获取到
<li v-for="item in items">
{{item.message}}
</li>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
items:[
{message:"注解"},
{message:"反射"},
{message:"多线程"},
]
}
})
</script>
4 Vue的事件绑定
关键字v-on:xx事件=“vue的对象中的methods中定义的对象”
<div id="app" v-on:click="say">
<button>点我点我</button>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message: "小羊学vue"
},
methods:{
say:function (){
alert(this.message)
}
}
})
</script>
结果:
5 Vue的双向绑定
使用指令:v-model=“data中对应的对象”,v-model会忽略所有表单的value、checked、selected特性的初始值而总是将Vue示例的数据作为数据来源,应该通过vue中的data选项申明初始值
5.1 输入框的双向绑定
<div id="app">
请输入:<input type="text" v-model="message">{{message}}
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message:""
}
})
</script>
5.2 单选框的双向绑定
<div id="app">
性别:
<input type="radio" name="sex" value="男" v-model="message">男
<input type="radio" name="sex" value="女" v-model="message">女
<p>选中值:{{message}}</p>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message:"男",
}
})
</script>
5.3 下拉框的双向绑定
由于在iOS中,如果下拉框没有初始值,那么这个下拉框会失效,所以需要设置一个默认或一个title,如下所示。
<div id="app">
<select name="apple" v-model="message">
<option disabled value="" selected>--请选择产品--</option>
<option>iPhone</option>
<option>iPad</option>
<option>iMac</option>
</select>
<p>选中了产品:{{message}}</p>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message:"",
}
})
</script>
6 Vue的组件
格式:Vue.component(组件名,参数prop,模板template);
在组件中,v-bind绑定的参数应该是prop中定义的参数
<div id="app">
<!--v-bind:这里的参数是对应prop中的参数,其实prop就是一个中间商,因为组件对象和vm对象是并列关系,不能直接相互调用,所以需要中间商来协调-->
<xiaoyang v-for="item in items" v-bind:item="item"></xiaoyang>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
Vue.component("xiaoyang",{
props:['item'],
template:'<li>{{item}}</li>'
})
var vm = new Vue({
el:'#app',
data:{
items:["Java","C++","Python"]
}
})
</script>
7 Axios异步通信
使用Axios进行异步通信相比于jQuery更加简洁,使用步骤:使用钩子函数mounted将数据取出(链式编程)然后使用data()方法进行接收,最后在前端渲染即可。
<div id="app" v-html>
{{info.name}}
<a v-bind:href="info.url">点我</a>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
<script>
var vm = new Vue({
el:"#app",
/*钩子函数,将数据取出来*/
data(){
return{
info:{/*设置为空,即可将json中的所有值取出来*/
}
}
},
mounted(){
axios.get('data.json').then(response=>(this.info=response.data));
}
})
</script>
{
"name":"小羊学Vue.js",
"url": "http://www.baidu.com",
"page": "1",
"isNonProfit":"true",
"address": {
"street": "含光门",
"city":"陕西西安",
"country": "中国"
},
"links": [
{
"name": "B站",
"url": "https://www.bilibili.com/"
},
{
"name": "4399",
"url": "https://www.4399.com/"
},
{
"name": "百度",
"url": "https://www.baidu.com/"
}
]
}
8 计算属性
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便做到这一点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销。
在vue中,可以使用computed属性属性作为缓存。
<div id="app" v-html>
{{p1()}}
{{p2}}
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
<script>
var vm = new Vue({
el:"#app",
methods:{
p1:function (){
var start = Date.now();
var sum = 0;
for (let i = 0; i < 100000; i++) {
sum+=i;
}
var end = Date.now();
return end-start;
}
},
computed:{
p2:function (){
var start = Date.now();
var sum = 0;
for (let i = 0; i < 100000; i++) {
sum+=i;
}
var end = Date.now();
return end-start;
}
}
})
</script>
也就是说在计算属性中,如果条件没有发生改变(参数,或者别的量),则始终给出第一次计算完成之后的结果,即p2中始终返回第一次计算100000所需事件,而p1则会给出每次计算所需要的时间,要注意这这两者的差别。
9 插槽slot
顾名思义,插槽就是一个页面中,总有一部分需要填充的,填充不同的内容显示不同的结果,前面的component组件中就是设置一个框架,总有需要填充的部分,而这填充的内容不一定非得是数据,也可以是某一个标签,比如li、div之类的。具体使用如下:注意需要做两次slot绑定
<div id="app">
<!--插槽的实现依赖于组件-->
<todo>
<!--前端需要用slot进行绑定插槽-->
<todo-title slot="todo-title" v-bind:title="title"></todo-title>
<todo-item slot="todo-item" v-for="item in items" v-bind:item="item"></todo-item>
</todo>
</div>
<script crossorigin="anonymous" integrity="sha512-BKbSR+cfyxLdMAsE0naLReFSLg8/pjbgfxHh/k/kUC82Hy7r6HtR5hLhobaln2gcTvzkyyehrdREdjpsQwy2Jw==" src="https://lib.baomitu.com/vue/2.6.12/vue.min.js"></script>
<script>
Vue.component("todo",{
template: '<div>\n' +
/*注意这里也需要做一个slot的绑定*/
' <slot name="todo-title"></slot>\n' +
' <ul>\n' +
' <slot name="todo-item"></slot>\n' +
' </ul>\n' +
'</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<p>{{title}}</p>'
});
Vue.component("todo-item",{
props:['item'],
template: '<li>{{item}}</li>'
})
var vm = new Vue({
el:'#app',
data:{
title:"小小羊学习课程",
items:["Java","Python","Android"]
}
})
</script>
10 自定义事件内容分发
我们想实现的一个效果是点击删除按钮,就可以删除对应的记录,也就是说删除data中items里面的对应
项目,那么如何实现呢?
分析:由于组件和vm对象是不同的,也就是非嵌套关系,那么组件中写remove方法是无法作用到vue对象中的data属性的,也就无法做到删除对应的item,那么如何让组件中的remove方法作用到data呢,可以通过在vm对象中也写一个删除方法,叫做removeItems方法,通过传入index,实现删除data中的对应item,那如何将组件中的remove方法与vue对象中的removeItems方法联系起来呢?一种方法就是在remove中使用this.$emit(“自定义事件名”,参数(index));然后在前端视图层中使用v-on:自定义事件名=“removeItems(index)”即可
11 vue-router路由
使用路由进行页面跳转
由于vue只能进行单个页面处理,所以需要进行页面跳转时需要使用vue-router。
步骤:
- 先在components文件夹下把需要的组件写好
- 在router文件夹写编写一个index.js文件,编写路由
- 在main.js文件下导入router文件夹,然后配置路由
- 在App.vue中写router-link和router-view
//index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
//导入组件
import Content from "../components/Content"
import Main from "../components/Main"
//安装路由
Vue.use(VueRouter)
export default new VueRouter({
routes:[
{
// 路由路径
path: '/content',
//路由名字
name: 'content',
//组件
component: Content
},
{
path: '/main',
name: 'main',
component: Main
}
]
})
//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'
import router from './router' //自动扫描对应的js文件
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: '#app',
//配置路由
router,
components: { App },
template: '<App/>'
})
9 路由嵌套
实现的效果:在一个页面中,嵌套其他组件,也就是说只改变一部分组件
实现方式:在index.js中,对需要嵌套的组件,添加children属性,在该属性中添加路由即可,前提是要写好对应的组件,以及在需要被嵌套的Vue中添加router-link和对应的位置添加router-view
export default new VueRouter({
routes: [
{
path: "/login",
name: "login",
component: Login
},
{
path: "/main2",
name: "main2",
component: Main2,
children:[
{
path:'/user/profile',
component:Profile
},{
path:'/user/List',
component:List
}
]
},
]
})
10 参数传递及重定向
一个坑:在vue文件中,不能直接将元素{{xxx}}直接放在根节点下
参数传递:在index.js文件中,在path后面加(:参数),表示要传递参数,设置props为true,,在前端vue中,在export暴露id(参数),然后在template中获取参数
<router-link :to="{name:'Profile',params:{id:1}}">个人信息</router-link>
<template>
<div>
<h3>个人信息</h3>
{{id}}
</div>
</template>
export default {
props: ['id'],
name: "Profile"
}
重定向:在路由添加的时候添加属性redirect:"xxx路由"即可
11 404以及路由钩子
404的实现很简单,就是先创建一个404组件,然后在index.js中设置一个默认路由即可。
路由钩子,两个属性:beforeRouteEnter、beforeRouteLeave,见名知义,不解释,和AOP那个很像,可以把axios放在beforeRouteEnter里面,具体如下。
beforeRouteEnter:(to,from,next)=>{
console.log("进入路由之前");
next(vm => {
vm.getData()
});
},
methods:{
getData:function (){
this.axios({
method: "get",
url: "http://127.0.0.1/static/mock/data.json",
}).then(response=>(console.log(response)))
}
}
解释:next()表示继续执行下面的内容,next(url)重定向,next(vm =>{}),表示操作当前的vm对象,在例子中给出的就是利用vm操作该对象中的getData方法。
完结撒花,入门vue了(开始我的springboot)