传统的mvp模式
该编码方式一般用于普通操作dom方式,改变视图后通过控制器,进行大量dom操作,调用数据或者操作视图,核心是在p层
mvvm模式
也就是说使用vue进行前端开发,我们只需要关心view层
和Model层就行
,操作dom就由vue来实现。在vm层中的实现主要使用了es5的object.definproperties和虚拟dom的机制。
new
一个Vue实例(也就是根实例){{}}
输出数据,只有被Vue实例接管的dom节点才能输出。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>第一个vue实例title>
<script type="text/javascript" src="./vue.js">script>
head>
<body>
<div id="app">{{content}}div>
<script type="text/javascript">
var app = new Vue({
el: '#app', 实例接管的dom
data: {
content: 'hello world!',
}
});
2秒后,修改显示内容
setTimeout(()=>{app.$data.content='hello poorpenguin!'},2000);
script>
body>
html>
v-model="变量名"
v-on:
简写@)监听dom事件 v-on:事件="方法名"
或者@事件="方法名"
v-for="item in items"
或者v-for="(item, index) in items(index为数组项下标)"
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="./vue.js">script>
head>
<body>
<div id="todolist">
<input type="text" v-model="inputValue"/>
<button @click="add">添加button>
<ul>
<li v-for="item in list">{{item}}li>
ul>
div>
<script type="text/javascript">
var todolist = new Vue({
el: '#todolist',
data: {
list: [],
inputValue: '',
},
methods: {
add(){
this.list.push(this.inputValue);
this.inputValue = '';
},
}
});
script>
body>
html>
通过Vue
实例接管的dom元素,我们就可以看成是一个组件。相对于全局注册
和局部注册
的组件来说,Vue
实例就是父组件。
vue
实例。局部组件是在局部注册的。
使用一个普通的js对象定义组件,再在Vue实例中注册components:{}
。
<div id="todolist">
<input type="text" v-model="inputValue"/>
<button @click="add">添加button>
<ul>
<to-do-list :content="item" :index="index" v-for="(item, index) in list">to-do-list>
ul>
div>
<script type="text/javascript">
var ToDoList = {
props: ['content','index'],
template: '{{index}}.{{content}} ',
};
var todolist = new Vue({
el: '#todolist',
components: {
ToDoList: ToDoList, //可以ES6简写 ToDoList,
//或者'to-do-list': ToDoList,
},
data: {
list: [],
inputValue: '',
},
methods: {
add(){
this.list.push(this.inputValue);
this.inputValue = '';
},
}
});
script>
通过 Vue.component
来创建组件,就是全局注册的组件。
<div id="todolist">
<input type="text" v-model="inputValue"/>
<button @click="add">添加button>
<ul>
<to-do-list :content="item" :index="index" v-for="(item, index) in list">to-do-list>
ul>
div>
<script type="text/javascript">
Vue.component('to-do-list',{
props: ['content','index'],
template: '{{index}}.{{content}} ',
});
var todolist = new Vue({
el: '#todolist',
data: {
list: [],
inputValue: '',
},
methods: {
add(){
this.list.push(this.inputValue);
this.inputValue = '';
},
}
});
script>
props
和v-bind
向子组件传递数据(父组件 → 子组件):
在子组件中,通过props:['变量名1','变量名2'...]
定义接收数据的变量。
Vue.component('to-do-list',{
props: ['content','index'],
template: '{{index}}.{{content}} ',
});
在父组件中,通过v-bind:子组件变量 = "变量"
向子组件中定义的变量传递数据。
<to-do-list :content="item" :index="index" v-for="(item, index) in list">to-do-list>
this.$emit()
向父级组件发送事件(数据)(子组件 → 父组件)子组件通过 $emit('子事件1', 参数)
方法向外派发事件,传递参数(可选)。
Vue.component('to-do-list',{
props: ['content','index'],
template: '{{index}}.{{content}} ',
methods: {
deleteItem: function(){
this.$emit('delete',this.index);
}
}
});
父组件通过v-on:子事件1= "方法"
来监听子组件的事件,和接收参数。
<div id="todolist">
<input type="text" v-model="inputValue"/>
<button @click="add">添加button>
<ul>
<to-do-list
:content="item"
:index="index"
v-for="(item, index) in list"
@delete="deleteSonItem"
>to-do-list>
ul>
div>
<script type="text/javascript">
Vue.component('to-do-list',{
....
});
var todolist = new Vue({
el: '#todolist',
data: {
list: [],
inputValue: '',
},
methods: {
add(){
this.list.push(this.inputValue);
this.inputValue = '';
},
deleteSonItem(index){ //接收子组件的参数
this.list.splice(index,1);
}
}
});
script>
new Vue()
得到的Vue实例,叫做根实例。全局注册
和局部注册
的组件都是一个个Vue实例。Vue
实例上的属性和方法。 var vm = new Vue({
el: '#todolist',
data: {
list: [],
inputValue: '',
},
methods: {
add(){
this.list.push(this.inputValue);
this.inputValue = '';
},
deleteSonItem(index){
this.list.splice(index,1);
}
}
});
console.log(vm);
常用的实例属性和方法
生命周期函数: 实例化过程的某一时刻自动执行的函数
首次加载页面时
首次加载页面时,不会走这两个钩子,只有当数据发生改变时才会执行:
执行销毁需要调用:vm.$destroy()
生命周期函数不需要写在methods
对象中,直接放在Vue实例中即可。
var vm =new Vue({
el: '#app';
beforeCreate: function(){},
created: function(){},
beforeMount: function(){},
mounted: function(){},
beforeUpdate: function(){},
updated: function(){},
beforeDestroy: function(){},
destroyed: function(){},
});
{{}}
<div id="app">
<div>{{str}}div>
<div v-text="str">div>
<div v-html="str">div>
<hr>
<div>{{str + ' poorpenguin'}}div>
<div v-text="str + 'poorpenguin'">div>
<div v-html="str + 'poorpenguin'">div>
<hr>
<div>{{num+1}}div>
<div v-text="num + 1">div>
div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
str: 'hello
',
num: 1,
},
});
script>
当data中的任何值发生改变的时候,页面会重新渲染。
所以一个需求如用computed、methods、watch都可以实现的话,推荐用computed、既简洁性能又高
计算属性的会缓存上一次计算的结果,只有当计算结果依赖的属性没有发生改变的时候,是不会重新计算的。
<div id="app">
<div>{{fullname}}div>
<div>{{age}}div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
word: 'hello',
name: 'poorpenguin',
age: 25,
},
computed: {
fullname: function(){
console.log('重新计算了一次!');
return this.word+' '+this.name;
}
}
});
script>
计算属性默认是只有getter, 也就是可以直接计算属性:function(){...}
这样写
computed: {
fullname: function(){
console.log('重新计算了一次!');
return this.word+' '+this.name;
}
}
如果要使用setter,计算属性就要是一个对象。
<div id="app">
<div>{{fullname}}div>
<div>{{age}}div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
word: 'hello',
name: 'poorpenguin',
age: 25,
},
computed: {
fullname: {
get: function(){
return this.word+''+this.name;
},
set: function(value){
value可以获得通过vm.fullname设置新的计算属性,就可以手动改变所依赖的变量。
var arr = value.split(' ');
this.word = arr[0];
this.name = arr[1];
}
}
}
});
script>
当数据发生变化,重新渲染页面时,会重新执行页面调用的方法。
<div id="app">
<div>{{fullname()}}div>
<div>{{age}}div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
word: 'hello',
name: 'poorpenguin',
age: 25,
},
methods: {
fullname: function(){
console.log('重新计算了一次!');
return this.word+' '+this.name;
}
}
});
script>
可以监听数据的变化,并执行相应的回调函数。
<div id="app">
<div>{{fullname}}div>
<div>{{age}}div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
word: 'hello',
name: 'poorpenguin',
fullname: 'hello poorpenguin',
age: 25,
},
watch: {
word: function(){
console.log('执行了一次!');
this.fullname = this.word+' '+this.name;
},
name: function(){
console.log('执行了一次!');
this.fullname = this.word+' '+this.name;
}
}
});
script>
使用v-bind:class="js表达式"
或:class="js表达式"
绑定样式,可以和元素原本的class属性
共存
vue中给dom元素绑定class方式
<div :class="{activated: isActivated}">
<div :class="[activated1,activated2]">
vue中给dom元素绑定style内联样式
<div :style="styleObj">
写法一:
<div :style="[styleObj1, {fontSize: '14px'}]">
写法二:
<div :style="[styleObj1, styleObj12]">
v-命令后面是一个js表达式,所以可以直接给class绑定一个对象。
<div id="app">
<h1 v-bind:class="{activated: isActivated }" v-on:click="clickH1">Hello poorpenguinh1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
isActivated: false,
},
methods: {
clickH1: function(){
this.isActivated = !this.isActivated;
},
}
});
script>
数组中每一项都是一个对象,剩下的就可以自由发挥了。
<style>
.activated-color{
color: red;
}
.activated-size{
font-size: 14px;
}
style>
<div id="app">
<h1 v-bind:class="[activated1,activated2]" v-on:click="clickH1">Hello poorpenguinh1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
activated1: '',
activated2: '',
},
methods: {
clickH1: function(){
this.activated1 = this.activated1 === ''? 'activated-color':'';
this.activated2 = this.activated2 === ''? 'activated-size':'';
},
}
});
script>
直接绑定一个对象。
<div id="app">
<h1 v-bind:style="styleObj" v-on:click="clickH1">Hello poorpenguinh1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
styleObj: {
color: '',
fontSize: '',
}
},
methods: {
clickH1: function(){
this.styleObj.color = this.styleObj.color === ''? 'red':'';
this.styleObj.fontSize = this.styleObj.fontSize === ''? '14px':'';
},
}
});
script>
数组中每一项都是一个对象。
<div id="app">
<h1 v-bind:style="[styleObj1, styleObj2]" v-on:click="clickH1">Hello poorpenguinh1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
styleObj1: {
color: '',
},
styleObj2: {
fontSize: '',
}
},
methods: {
clickH1: function(){
this.styleObj1.color = this.styleObj1.color === ''? 'red':'';
this.styleObj2.fontSize = this.styleObj2.fontSize === ''? '14px':'';
},
}
});
script>
当v-if
的值为false
,dom元素是不会挂载到页面上的。
<div id="app">
<h1 v-if="show">Hello poorpenguinh1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
show: false,
}
});
script>
v-if/v-else-if/v-else 必须连在一起使用,中间不能被任何标签分隔,不然会报错。
<div id="app">
<h1 v-if="show === 'a'">This is Ah1>
<h1 v-else-if="show === 'b'">This is bh1>
<h1 v-else>This is othersh1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
show: 'a',
}
});
script>
当v-show
的值为false,是dom元素在dom树中还是存在的。
<div id="app">
<h1 v-show="show">This is Ah1>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
show: false,
}
});
script>
<div id="app">
<div v-if="show">用户名:<input type="text">div>
<div v-else>邮箱:<input type="text">div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
show: true,
}
});
script>
Vue在数据更新的时候,会尝试复用已经存在的 dom,使用 key 属性来设置 dom 的唯一性,这样可以避免复用了。
<div id="app">
<div v-if="show">用户名:<input type="text" key="username">div>
<div v-else>邮箱:<input type="text" key="email">div>
div>
渲染列表我们可以使用 item为数组项,index为下标 在正常项目开发的时候,后端返回给前端的数据都会带有数据表的 set有两种使用方式 两种使用的方式一样。 set()改变数组 set()改变对象 用来包裹多个列表,该标签不会被渲染到页面上。7.1 渲染数组
<div id="app">
<div v-for="(item,index) of list">{{index+1}}--{{item}}div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
list: ['poorpenguin','阿西吧','苟','铁骨铮铮王'],
}
});
script>
7.2 渲染对象
<div id="app">
<div v-for="(item,key,index) of userInfo">{{index+1}}. {{key}} : {{item}}div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
userInfo: {
name: 'poorpenguin',
age: 25,
sex: 'male',
salary: 'secret',
},
}
});
script>
7.3 key
主键id
,建议将id
作为循环项的key值。 <div id="app">
<div v-for="(item,index) of users"
:key="item.id">{{index+1}}——{{item.name}}——{{item.remark}}div>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
users: [
{
id: '123',
name: '王境泽',
age: '20',
remark: '哎,真香!'
},
{
id: '124',
name: '鲁迅',
age: '90',
remark: '横眉冷对千夫指,俯首甘为孺子牛!'
},
{
id: '125',
name: '张学友',
age: '50',
remark: '食屎啦你!'
},
{
id: '126',
name: '王建森',
age: '52',
remark: '先赚他一个亿!'
},
]
}
});
script>
7.4 改变数组和对象的内容,保证页面实时响应
7.5 使用set方法改变数组和对象中的值,保证页面实时响应
Vue.set(vm.数组, 下标, 内容);
vm.$set(vm.数组, 下标, 内容);
<div id="app">
<template v-for="(item,index) of users">
<h1>{{item.name}}h1>
<div>{{item.remark}}div>
<hr>
template>
div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
users: [
{
id: '123',
name: '王境泽',
age: '20',
remark: '哎,真香!'
},
{
id: '124',
name: '鲁迅',
age: '90',
remark: '横眉冷对千夫指,俯首甘为孺子牛!'
},
{
id: '125',
name: '张学友',
age: '50',
remark: '食屎啦你!'
},
{
id: '126',
name: '王建森',
age: '52',
remark: '先赚他一个亿!'
},
]
}
});
script>
Vue.set(vm.对象, 键名, 键值);
vm.$set(vm.对象, 键名, 键值);
7.6
来包裹多个标签
<template v-for="(item,index) of users">
<h1>{{item.name}}h1>
<div>{{item.remark}}div>
<hr>
template>