文章目录
Vue核心
Vue简介
介绍与描述
- 动态构建用户界面的渐进式JavaScript框架
- 作者:尤雨溪
Vue的特点
-
遵循MVVM模式
-
编码简洁,体积小,运行效率高,适合移动/PC端开发
-
它本身只关注UI,可以引入其它第三方库开发项目
与其他JS框架的关联
- 借鉴 Angular 的模板和数据绑定技术
- 借鉴 React 的组件化和虚拟DOM技术
Vue周边库
- vue-cli:vue脚手架
- vue-resource
- axios
- vue-router:路由
- vuex:状态管理
- element-ui:基于vue的UI组件库(PC端)
Vue基础使用
<div id="app">
{{msg.substring(0,2)}}
</div>
<script src="./js/vue_2.0.js"></script>
<script>
const { createApp } = Vue
const app = new Vue({
el: "#app",
data: {
msg: "欢迎使用Vue",
}
});
</script>
在使用data定义变量的时候,也可以选择定义很多其他不同的类型
在div中使用变量时,也可以使用各种方法,例如substring()
效果图
注意:
- 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
- root容器里的代码被称为Vue模板
- Vue实例与容器是一一对应的
- 真实开发中只有一个Vue实例,并且会配合着组件一起使用
- {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性
- 一旦data中的数据发生变化,那么模板中用到该数据的地方也会自动更新
模板语法
插值表达式
<div id="app">
<!-- 插值表达式 -->
{{msg.substring(0,2)}}
{{user.name}}
{{user.msg}}
<br>
{{lists[0]}}
{{lists}}
<br>
{{users}}
{{users[0].name}} {{users[0].age}}
</div>
<script src="./js/vue_2.0.js"></script>
<script>
const { createApp } = Vue
// 创建一个vue实例
const app = new Vue({
// 用来给vue创建一个作用域
el: "#app",
// data用来给Vue定义一些相关的数据
data: {
msg: "欢迎使用Vue",
user: {
msg: "user msg",
name: "user name",
},
lists: ["BeiJing","ShangHai"],
users: [{name:"小强",age:"25"},
{name:"小红",age:"21"}],
},
});
</script>
插值闪烁
什么是插值闪烁?当我们的网速很慢,网页无法全部加载的时候,我们的变量就会显而易见的出现,显示为{{msg}},那么我们该如何解决呢?在标签内使用v-text或者v-html属性来使用变量值
<div id="app">
{{msg}}
<!-- 下面的方式不会有插值闪烁 -->
<h1 v-text="msg"></h1>
<h1 v-html="aaa"></h1>
</div>
<script src="./js/vue_2.0.js"></script>
<script>
const { createApp } = Vue
const app = new Vue({
el: "#app",
data: {
msg: "<em>欢迎使用Vue</em>",
aaa: "<em>hello!!!</em>"
}
});
</script>
总结:
Vue模板语法包括两大类:
- 插值语法
- 功能:用于解析标签体内容
- 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有区域
- 指令语法
- 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
- 举例:或简写为,xxx同样要写js表达式,且可以直接读取到data中的所有属性
- 备注:Vue中有很多的指令,且形式都是v-???,此处我们只是拿v-bind举个例子
数据绑定
<div id="root">
单向数据绑定:<input type="text" v-bind:value="name"><br>
双向数据绑定:<input type="text" v-model:value="name">
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'JOJO'
}
})
</script>
总结
Vue中有2种数据绑定的方式:
- 单向绑定(v-bind):数据只能从data流向页面
- 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
备注
- 双向绑定一般都应用在表单类元素上(如:、、等)
- v-model:value可以简写为v-model,因为v-model默认收集的就是value值
el与data的两种写法
<body>
<div id="app">
<h1>Hello,{{name}}!</h1>
</div>
<script>
Vue.config.productionTip = false
//el的两种写法:
// const vm = new Vue({
// // el:'#root', //第一种写法
// data:{
// name:'JOJO'
// }
// })
// vm.$mount('#root')//第二种写法
//data的两种写法:
new Vue({
el:'#root',
//data的第一种写法:对象式
// data:{
// name:'JOJO'
// }
//data的第二种写法:函数式
data(){
return{
name:'WhiteHang'
}
}
})
</script>
</body>
Vue.config.productionTip = false
Vue.config.productionTip = false这句代码是在入口文件里的
- 看看没有这句话的效果
这张图上面 显示出来的就是没有这句代码的效果 他说 (You are running Vue in development mode.Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html) 阻止了生产模式,此时是以开发模式运行的
- 没有Vue.config.productionTip = false这句代码,它会显示你生产模式的消息
- 有这句话效果
有这句代码后,他没有显示 (You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html) 这条消息
- 有了Vue.config.productionTip = false这句代码,它会阻止你显示显示生产模式的消息
总结:
el有两种写法:
- 创建实例对象的时候配置el属性
- 先创建Vue实例,随后vm.$mount(‘#root’)指定el属性
data有两种写法:
- 对象式
- 函数式
- 如何选择:目前那种写法都可以,以后学到组件data必须用函数否则会出错误
由Vue管理的函数,一定不要写箭头函数,否则this 就不再是Vue实例了
MVVM模型(重点)
MVVM模型图解
- MVVM模型:
- M:模型(Model),data中的数据,相当于数据层,数据就是即将在View层展示的。
- V:视图(View),模板代码,字面意思就是直观的讲页面呈现给数据。
- VM:视图模型(ModelView),Vue实例,类似于中间件的用法主要用于Model和View之间的桥梁,通过数据的双向绑定即可两者之间的联系起来,并且保证数据视图的一致性。
值得一提的是在MVVM模型中,Model层和View层两者之间不能直接进行联系,必须通过ViewModel这个桥梁进行通信,主要表现在以下方面
*1.ViewModel层观察数据层变化,并对视图对应的内容进行实时更新
2.VIewModel层通过监听数据视图层变化,并能够通知数据发生相应的变化。
3.ViewModel层:把View需要的的层数据暴露,并且View层的数据绑定声明、指令声明、事件绑定声明负责,也就是处理View层的具体业务逻辑。ViewModel底层会做好绑定属性监听。当ViewModel中数据变化,View层会得到数据更新;而当View中声明了数据的双向绑定(通常是单元素),框架会监听View层(表单)值的变化。一旦值变化,View层绑定ViewModel中的数据也会得到自动更新
什么是MVVM模型
- Vue的设计受到了MVVM模型的启发,在文档中使用vm(view model)来表示vue的实例,那么,问题来了什么是MVVM模型呢?
- MVVM从字面意思来理解就是划分为 View 、model 、 VIewModel 三个部分,分别表达了 View(视图)、Model(数据)、ViewModel(负责两者之间的数据处理操作)。 这就类似于Mvc框架中的Model层、View层、congtroller层,MVVM的本质就是MVC的升级版,更好的应用于前端开发。
- Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。
MVVM模型特点
MVVm模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点:
- 低耦合性:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化时候View可以不变。
- 可重用性:你可以把一些试图逻辑放在一个ViewModel里面,让很多View重用这段试图逻辑。
- 独立开发性:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以容易设计界面并生成xmal代码。
- 可测试性:界面素是比较难于测试的,测试可以针对ViewModel来写。
总结
在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。
<body>
<div id="root">
<h2>名称:{{name}}</h2>
<h2>战队:{{rank}}</h2>
<h2>测试:{{$options}}</h2>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'uzi',
rank:'RNG'
}
})
</script>
</body>
效果:
总结
- data中所有的属性,最后都出现在了Vm身上
- Vm身上的所有属性及Vue原型身上的所有属性,在Vue模板中都可以直接使用
Vue中的数据代理
总结:
- Vue中的数据代理通过Vm对象代理data对象中属性操作(读/写)
- Vue中数据代理的好处:更加方便操作data中的数据
- 基本原理:
- 通过object.defineProperty()把data对象中所有属性添加到vm上。
- 为每一个添加到vm上的属性,都指定一个getter/setter。
- 在getter/setter内部去操作(读/写)data中对应的属性。
事件处理
事件的基本用法
<body>
<div id="root">
<h2>hello,{{name}}</h2>
<button v-on:click="showInfo1">点我提示信息1</button>
<button @click="showInfo2($event,66)">点我提示信息2</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'JOJO'
},
methods:{
showInfo1(event){
console.log(event)
},
showInfo2(evnet,num){
console.log(event,num)
}
}
})
</script>
</body>
总结:
- 使用 v-on:xxx或@xxx,其中xxx是事件名
- 事件的回调需要配置在Methods对象中,最终会在Vm上
- Methods中配置的函数,==不要用箭头函数!==否则this就不是Vm
- Methods中配置的函数,都是被Vue所管理的函数,this的指向是Vm或组件实例的对象
- @click=“demo”和@click=“demo($ecent)”效果一般,但后者可以传参
事件修饰符
<script type="text/javascript" src="../js/vue.js"></script>
<style>
*{
margin-top: 20px;
}
.demo1{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: skyblue;
}
.box2{
padding: 5px;
background-color: orange;
}
.list{
width: 200px;
height: 200px;
background-color: peru;
overflow: auto;
}
li{
height: 100px;
}
</style>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!-- 阻止默认事件 -->
<a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>
<!-- 阻止事件冒泡 -->
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
</div>
<!-- 事件只触发一次 -->
<button @click.once="showInfo">点我提示信息</button>
<!-- 使用事件的捕获模式 -->
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
<!-- 只有event.target是当前操作的元素时才触发事件 -->
<div class="demo1" @click.self="showInfo">
<button @click="showInfo">点我提示信息</button>
</div>
<!-- 事件的默认行为立即执行,无需等待事件回调执行完毕 -->
<ul @wheel.passive="demo" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods:{
showInfo(e){
alert('同学你好!')
},
showMsg(msg){
console.log(msg)
},
demo(){
for (let i = 0; i < 100000; i++) {
console.log('#')
}
console.log('累坏了')
}
}
})
</script>
总结
Vue的事件修饰符:
- prevent:阻止默认事件(常用)
- stop:阻止事件冒泡(常用)
- once:事件只触发一次(常用)
- capture:使用事件捕获模式
- self:只有event.target是当前操作的元素时才触发事件
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕
修饰符可以连续写,比如这么用:@click.prevent.stop=“showInfo”。
<body>
<div id="app" class="main" @click="divClick">
<div class="aa">
<button @click.stop="btnClick">按钮</button>
</div>
</div>
<script src="js/vue.js"></script>
<script>
/*
事件修饰符
用来和事件连用,决定事件出发的条件
或者阻止事件的触发机制
事件的冒泡:
点击div里的按钮,div被点击的事件也被触发
.stop修饰符:
用来阻止事件冒泡
*/
const app = new Vue({
el : "#app",
data:{},
methods:{
btnClick() {
alert("button被点击了");
},
divClick() {
alert("div被点击了");
}
}
});
</script>
</body>
阻止标签
<body>
<div id="app">
<a href="https://www.baidu.com" @click.prevent="aClick">百度一下</a>
<form action="aaa">
<input type="text" required>
<input type="submit" @click="submitClick">
</form>
</div>
<script src="js/vue.js"></script>
<script>
/*
.prevent:阻止标签的默认行为
*/
const app = new Vue({
el: "#app",
data: {},
methods: {
aClick() {
location.href = "http://www.douyu.com";
},
submitClick() {
alert("submit被点击")
}
},
});
</script>
</body>
只触发一次按键
<body>
<div id="app">
<a href="https://www.baidu.com" @click.prevent.once="aClick">百度一下</a>
</div>
<script src="js/vue.js"></script>
<script>
/*
.once:只触发一次,之后执行标签的默认行为
*/
const app = new Vue({
el: "#app",
data: {},
methods: {
aClick() {
window.open("http://www.douyu.com");
}
},
});
</script>
</body>
键盘事件
<body>
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<input type="text" placeholder="按下回车提示输入" @keydown.enter="showInfo">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods: {
showInfo(e){
console.log(e.target.value)
}
},
})
</script>
效果:
总结:
键盘上每个按键都有自己的名称和编码,例如:Enter(13)。而Vue还对一些常用按键起了别名方便使用
Vue中常用的按键别名:
- 回车:Enter
- 删除:delete(捕获“删除”和“退格”键)
- 退出:Esc
- 换行:Tab(特殊,必须配合keydown去使用)
- 上:up
- 下:down
- 左:left
- 右:right
注意:
- 系统修饰键(用法特殊):ctrl、alt、shift、meta
- 配合keyup使用:按下修饰键同时,按下其他键,随后其他键,随后释放其他键,事件才被触发
- 配合keydown使用:正常触发事件
- 可以使用keyCode去指定具体按键,比如:@keydown.13=“showInfo”,但不推荐这样子使用
- Vue.config.keyCodes.自定义键名=键码,可以自定义按键别名
案例
<body>
<div id="app" @keyup.enter="valid">
<input type="text" v-model="input">
<input type="button" value="提交" @click="valid">
</div>
<script src="js/vue.js"></script>
<script>
/*
对键盘按键进行修饰
.enter
.tab
.delete(删除和退格)
.space
.up
.down
.left
.right
*/
const app = new Vue({
el: "#app",
data: {
input : "",
},
methods: {
valid() {
if(this.input == ""){
alert("用户名不能为空");
}
// alert("键盘被按下");
}
},
});
</script>
</body>
案例(全局组件)
代码
一
<body>
<div id="app">
<login></login>
</div>
<div id="container">
<login></login>
</div>
<script src="js/vue.js"></script>
<script>
/*
全局组件注册
参数1:组件名称
参数2:组件配置对象
template:用来书写组件的html代码
(注意:template中必须有且只有一个容器)
*/
Vue.component('login',{
template:"<div><h1>用户登录</h1></div>",
});
const app = new Vue({
el: "#app",
data: {},
});
const container = new Vue({
el: "#container",
data: {},
});
</script>
</body>
二
<body>
<div id="app">
<login :username="username" @aaa="findAll"></login>
</div>
<!-- 定义局部组件 -->
<template id="loginTemplate">
<div>
<h1>用户登录:{{username}}</h1>
<ul>
<li v-for="(item,index) in lists">
{{index}} --- {{item}}
</li>
</ul>
<button @click="change">触发组件中的事件</button>
</div>
</template>
<script src="js/vue.js"></script>
<script>
// 定义一个局部组件
let login = {
template: "#loginTemplate",
// props: ["name","age"]
data() {
return {
name:"xiaoqiang",
lists:['java','c++','python']
}
},
props:['username'],
methods: {
change() {
// alert(this.name);
this.$emit('aaa');
}
},
}
const app = new Vue({
el: "#app",
data: {
username:"zhangsan",
age:23
},
methods: {
findAll() {
alert("Vue实例中定义的函数");
}
},
components:{
// 挂载组件
/*
第一个login:我的组件的名
第二个login:要挂载的组件名
*/
login
}
});
</script>
</body>
三
<body>
<div id="app">
<!-- <a href="login">点我登录</a>
<a href="register">点我注册</a> -->
<router-link tag="button" to="/login?id=21">登录</router-link>
<router-link tag="button" to="/register/21/zhangsan">注册</router-link>
<!-- 需要在页面上展示视图 -->
<router-view></router-view>
</div>
<script src="js/vue.js"></script>
<script src="js/vue-router.js"></script>
<script>
/*
1、router.js放在vue.js下面
2、创建路由对象写在创建组件模板下面
*/
let login = {
template: '<h1>登录{{this.$route.query.id}}</h1>'
}
let register = {
template: '<h1>注册</h1>',
created() {
console.log(this.$route.params.id + "===>" + this.$route.params.name);
}
}
// 创建路由对象
const router = new VueRouter({
// 定义路由规则
routes: [
{path:'/',component:register},
{path:'/login',component:login},
// path:路由的路径
// component:路径对应的组件
{path:'/register/:id/:name',component:register},
],
});
const app = new Vue({
el: "#app",
data: {},
// 在当前vue实例中挂载路由
methods: {
},
router:router,
});
</script>
</body>
四
<body>
<div id="app">
<router-link to="/product">商品管理</router-link>
<router-view></router-view>
</div>
<template id="product">
<div>
<h1>商品管理</h1>
<router-link to="/product/add">商品添加</router-link>
<router-link to="/product/edit">商品编辑</router-link>
<router-view></router-view>
</div>
</template>
<script src="js/vue.js"></script>
<script src="js/vue-router.js"></script>
<script>
let product = {
template:"#product"
}
let add = {
template:"<h4>商品添加</h4>"
}
let edit = {
template:"<h4>商品编辑</h4>"
}
const router = new VueRouter({
routes: [
{
path:'/product',component:product,
children: [
{
path:'add',
component:add
},
{
path:'edit',
component:edit
}
]
},
]
});
const app = new Vue({
el: "#app",
data: {},
router:router
});
</script>
</body>