Vue.js基础
Vue.js是什么
Vue.js是一套构建用户界面的 渐进式框架。它 的目标是通过尽可能简单的 API 实现响应的数据绑 定和组合的视图组件。它不仅易于上手,还便于与第三方库或既有项目整合。
模板语法
Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。在底层的实现上, Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,在应用状态改变时, Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。
MVVM模式
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为 抽象化,让我们将视图 UI 和业务逻辑分开MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model)Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。
1.Vue的基本使用
1.0Vue实例:构造函数
每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例 启动的:
var vm = new Vue({ // 选项})
在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。
1.1声明式渲染--插值表达式
Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统:
<div id="app">
<h4>{{message}}</h4>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
</script>
<script>
var app = new Vue({ //创建VM对象
el:"#app", //指定锚定DOM根元素
data:{
message:"Hello Vue.js"
}
});
</script>
- 现在数据和 DOM 已经被绑定在一起,所有的元素都是响应式的
1.2绑定DOM属性
语法 vbind:元素属性="模型属性" 简写 :元素属性="模型属性
<span v‐bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
v-bind 属性被称为指令。指令带有前缀 v-,以表示它们是 Vue.js 提供的特殊属性。,它们会在渲染过的 DOM 上应用特殊的响应式行为。这个指令的简单含义是说:将这个元素节点的 title 属性和 Vue 实例的message 属性绑定到一起.
1.3VueJS的常用指令
v-on:监听DOM元素的事件,执行事件处理程序
一。语法 von:事件名="事件处理代码" 简写 @事件名="事件处理代码
<button v‐on:click="reverseMessage1">文字反转1</button>
<button v-on:click="reverseMessage2()">文字反转2</button>
二。事件传参
事件传参(其他参数,$event)
事件对象一定要用$event,必须是最后一个参数
如果事件直接绑定函数名称(不带括号),默认会传递事件对象作为事件处理函数的第一个参数
如果事件是函数调用绑定(带括号),必须显式传递事件参数对象(最后一个参数$event)
<button v-on:click="reverse1">文字反转1</button>
<button v-on:click="reverse2(1,$event)">文字反转2</button>
//部分代码:
methods:{
reverse1:function(event){
console.log(event.target);
this.message=this.message.split('').reverse().join('');
},
reverse2:function(id,event){
console.log(id,event.target);
this.message=this.message.split('').reverse().join('');
}
}
v-model:双向绑定
<p>{{message}}</p>
<input v‐model="message" />
**v-for循环指令--**操作数组和对象
语法 vfor="(item,index) in 列表"
//数组
<ol>
<li v‐for="todo in todos">
{{ todo.text }}
</li>
</ol>
//对象
<ul>
<li v-for="(value,key) in product">{{key}}--{{value}}</li>
</ul>
v-if和v-else
<h1 v-if="ok">Yes</h1><h1 v-else>No</h1>
v-if和v-show
v-if是根据表达式的值来决定是否渲染元素 v-show是根据表达式的值来切换元素的display css属性
<span v-if="flag">vue if</span>
<span v-show="flag">vue show</span>
1.3CSS与Style绑定
class 和style都是属性,可用 vbind 处理,只需要通过表达式计算出字符串结果即可。 不过,字符串拼接麻烦且易错。因此,Vue.js 做了增强。表达式结果的类型除了字符串之 外,还可以是对象或数组。
1)class绑定
对象绑定,一下active是否出现,由模型的isActive决定 一个{}
<div v‐bind:class="{ active: isActive }"></div>
class的动态绑定和与class静态属性共存
<div class="static" v‐bind:class="{ active: isActive, 'text‐danger':hasError }"> </div>
模型属性对象绑定
<div v‐bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text‐danger': false
}
}
数组
<div v‐bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text‐danger'
}
数据+表达式
<div v‐bind:class="[isActive ? activeClass : '', errorClass]"></div>
2)style绑定 字符串绑定
<div v‐bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
模型属性对象绑定:
<div v‐bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.content{
height:200px;
background-color:pink;
}
.border{
border:1px solid blue;
}
#header{
height: 80px;
background-color: greenyellow;
}
#footer{
height: 60px;
background-color:gainsboro;
}
.colorCss{
color:gold;
}
.fontCss{
font-size:14px;
font-weight: bold;
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
}
</style>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div id="header" :class="{border:isBorder}"><h1>网站头部</h1></div>
<div class="content" v-bind:style="styleObject">网站主体</div>
<div id="footer" :class="[cssObject.font,cssObject.color]" ><h2>网站底部</h2></div>
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
isBorder:true,
styleObject:{
color:"red",
fontSize:"24px",
textAlign:"center",
borderStyle:"2px",
borderColor:"yellow",
borderStyle:"dashed"
},
cssObject:{
color: 'colorCss',
font:'fontCss'
}
},
methods:{
}
})
</script>
</body>
</html>
2.组件基础
组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

1.全局注册
Vue.component(
'组件名称', {
props:[ '属性1', '属性2', ... ],
components: {子组件, ...},
data: function(){
return { ...模型定义... };
},
template: 'html字符串模板'
}
);
例如组件注册:
Vue.component('MyComponent', { // 选项})
使用组件:
<div id="example"> <my-component></my-component></div>
注意:自定义组件命名规则
1.短横线 my-component
2.驼峰式 MyComponent:在使用组件的时候只能在模板字符串中(组件中嵌套个组件)使用驼峰命名,在普通的标签中使用必须转换为短横线的方式
<ol>
<todo‐item v‐for="todo in todos" v‐bind:todo="todo" v‐
bind:key="todo.id"/>
</ol>
<script src="js/vue.js"></script>
<script>
Vue.component("todo‐item", {
props:['todo'],
template:"<li>{{todo.title}}</li>"
});
var app = new Vue({
el:"#app",
data:{
todos:[
{id:1, title:"跑步"},
{id:2, title:"学习Vue模板语法"},
{id:3, title:"写工作日记"},
]
}
});
</script>
2.局部注册
不必在全局注册每个组件。通过使用组件实例选项注册,可以使组件仅在另一个组件的作用域中可用:
<script>
var Child={
template:'<h2>我是子组件child</h2>'
}
Vue.component('Parent',{
components:{
'Child':Child
},
template:`<div>
<h1>我是父组件parent</h1>
<child></child>
</div>`
});
var vm=new Vue({
el:"#app"
})
</script>
3.组件关键特性
组件中的data必须是一个函数
Vue.component('button-counter',{
template:'<button @click="counter++">你单击了{{counter}}次</button>',
data:function(){
return {
counter:0
}
}
})
4.使用props传递数据--数组形式
组件实例的作用域是孤立的。不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。
<div id="app">
<blog‐post v‐for="(item,index) in articles"
:post="item" :key="item.index"></blog‐post>
</div>
<script>
Vue.component("blog‐post", {
props:['post'],
template: `<div class="blog‐post">
<h3>{{ post.title }}</h3>
<div v‐html="post.content"></div>
</div>`
});
new Vue({
el:"#app",
data:{
articles:[
{id:1,title:"博客标题1",content:"博客内容1..."},
{id:2,title:"博客标题2",content:"博客内容2..."},
{id:3,title:"博客标题3",content:"博客内容3..."} ]
}
});
</script>
5.使用自定义事件修改父组件数据
prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。
自组件要想修改父组件的数据或者将数据传回到父组件则使用自定义事件,在子组件内部使用$emit(事件名)触发父组件事件。在父组件内部使用子组件时,使用v-on:事件名或者@事件名编写事件处理程序,实现父组件数据的修改。
<div id="app">
<p :style="{fontSize:fontSize+'px'}">我是父组件文本</p>
<change-parent @enlarge-text="handle"></change-parent>
</div>
<script>
Vue.component("changeParent",{
template:`
<div>
<button @click='$emit("enlarge-text",5)'>改变父组件字体大小</button>
<button @click='$emit("enlarge-text",10)'>改变父组件字体大小</button>
</div>
`
})
var vm=new Vue({
el:"#app",
data:{
fontSize:10
},
methods:{
handle:function(val){
this.fontSize+=val;
}
}
})
</script>
6.事件,组件,数据传递综合案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<style>
.container{
width:200px;
margin: auto;
}
#header{
height:30px;
line-height: 30px;
background-color: paleturquoise;
text-align: center;
}
#footer{
height:40px;
line-height: 40px;
background-color: orange;
text-align: center;
}
.list-item{
border-top:1px solid bisque;
}
.qty{
width:20px;
}
a{
text-decoration: none;
}
.title{
width:50px;
}
</style>
</head>
<body>
<div id="app">
<my-cart></my-cart>
</div>
<script>
var CartHeader={
props:['title'],
template:`<div id="header">{{title}}的购物车</div>`
};
var CartList={
props:['list'],
template:`
<div id="content">
<div class="list-item" :key="item.id" v-for="item in list">
<span class="title">{{item.title}}</span>
<a href="" @click.prevent="sub(item.id)">-</a>
<input type="text" class="qty" :value="item.quantity" @blur="changeQty(item.id,$event)"/>
<a href="" @click.prevent="add(item.id)">+</a>
<button @click="del(item.id)">删除</button>
</div>
</div>`,
methods:{
del:function(id){
//让父组件删除
console.log(id);
this.$emit('del-data',id);
},
changeQty:function(id,event){
this.$emit("change-qty",{
id:id,
type:"change",
quantity:event.target.value
})
},
add:function(id){
this.$emit("change-qty",{
id:id,
type:"add"
})
},
sub:function(id){
this.$emit("change-qty",{
id:id,
type:"sub"
})
}
}
};
var CartFooter={
props:['list'],
template:`
<div id="footer" :list="list">汇总金额:{{total}}
</div>`,
computed: {
total:function(){
var sum=0;
this.list.forEach(item=>{
sum+=item.quantity*item.price;
})
return sum;
}
}
}
Vue.component('my-cart',{
data:function(){
return{
title:'李明亮',
list:[
{id:1,title:'洗衣机',price:3900,quantity:1},
{id:2,title:'笔记本电脑',price:5900,quantity:2},
{id:3,title:'电视机',price:2200,quantity:3},
{id:4,title:'硬盘',price:350,quantity:1},
]
}
},
methods:{
handleDelete:function(id){
var index=this.list.findIndex(item=>
item.id==id);
this.list.splice(index,1);
},
changeQty:function(value){
if(value.type=="change"){
this.list.some(item=>{
if(item.id==value.id)
{
item.quantity=value.quantity;
return true;
}
})
}else if(value.type=="add"){
this.list.some(item=>{
if(item.id==value.id)
{
item.quantity+=1;
return true;
}
})
}else{
this.list.some(item=>{
if(item.id==value.id)
{
item.quantity-=1;
return true;
}
})
}
}
} ,
template:`
<div class="container">
<cart-header :title="title"></cart-header>
<cart-list @change-qty="changeQty($event)" :list="list" @del-data="handleDelete($event)"></cart-list>
<cart-footer :list="list"></cart-footer>
</div>
`,
components:{
'cart-header':CartHeader,
'cart-list':CartList,
'cart-footer':CartFooter
}
})
var vm=new Vue({
el:"#app",
data:{
username:'黎瑜伽',
},
methods:{
}
})
</script>
</body>
</html>