文章目录
- 1.计算属性computed
- 2.监听watch
- 3.过滤器filter
- 4.表单、复选框
- 4.1. 多选checkbox
- 4.2. 单选radio
- 4.3.下拉select
- 5.修饰符
- 6.组件化
- 7.生命周期钩子函数
1.计算属性computed
什么是计算属性:属性不是具体值,而是通过一个函数计算出来的,随时变化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
<p>计算后反转字符串: {{ reversedMessage2() }}</p>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Runoob!'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
},
methods: {
reversedMessage2: function () {
return this.message.split('').reverse().join('')
}
}
})
</script>
</body>
</html>
这里可以比较一下计算和method之间的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="div">
<p>{{message}}</p>
<button id="btn" v-on:click="change">点击翻译成中文</button>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<!--引入vue js 外部文件-->
<script> //vue js 代码写在这里
var a = new Vue({
el: "#div",
data: { message: "good good study" },
methods: {
change: function () {
alert("测试");
this.message = "天天向上"
}
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="div">
<input v-model="firstName">
<input v-model="lastName">
<br />
<p>{{fullName}}</p>
</div>
<body>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
var vm = new Vue({
el: '#div',
data: {
firstName: 'zheng',
lastName: 'zeling'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
</html>
因为 input 框使用了 v-model 双向绑定了 firstName 这个数据值,所以当修改输入框内容时,firstName 也跟随变化;而又因为 computed 计算属性 fullName 的返回值依赖于 firstName,所以一旦 firstName 发生变化,fullName 马上被触发
computed (计算属性) 和 methods (方法) 的区别:
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
也就是说:
函数执行需要 数据属性里面的 message 值作为参数。
● 如果使用 methods 执行函数,vue 每次都要重新执行一次函数,不管message 的值是否有变化;
● 如果使用computed 执行函数,只有当message 这个最初的数据发生变化时,函数才会被执行。(依赖-监测数据变化)
2.监听watch
监听属性 watch,我们可以通过 watch 来响应数据的变化。
以下实例通过使用 watch 实现计数器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p style="font-size:25px;">计数器: {{ counter }}</p>
<button @click="counter++" style="font-size:25px;">点我</button>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
counter: 1
}
});
vm.$watch('counter', function (nval, oval) { // new old
alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 某些结果是基于之前数据实时计算出来的,我们可以利用计算属性。来完成 -->
<ul>
<li>西游记; 价格:{{xyjPrice}},数量:<input type="number" v-model="xyjNum"> </li>
<li>水浒传; 价格:{{shzPrice}},数量:<input type="number" v-model="shzNum"> </li>
<li>总价:{{totalPrice}}</li>
{{msg}}
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
//watch可以让我们监控一个值的变化。从而做出相应的反应。
new Vue({
el: "#app",
data: {
xyjPrice: 99.98,
shzPrice: 98.00,
xyjNum: 1,
shzNum: 1,
msg: ""
},
computed: {
totalPrice(){
return this.xyjPrice*this.xyjNum + this.shzPrice*this.shzNum
}
},
watch: {
xyjNum: function(newVal,oldVal){
if(newVal>=3){
this.msg = "库存超出限制";
this.xyjNum = 3
}else{
this.msg = "";
}
}
},
})
</script>
</body>
</html>
3.过滤器filter
定义filter组件后,管道符后面跟具体过滤器{{
user.gender
|
gFilter
}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- 过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 -->
<div id="app">
<ul>
<li v-for="user in userList">
{{user.id}} ==> {{user.name}} ==> {{user.gender == 1?"男":"女"}} ==>
{{user.gender | genderFilter}} ==> {{user.gender | gFilter}}
</li>
</ul>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
// 全局过滤器
Vue.filter("gFilter", function (val) {
if (val == 1) {
return "男~~~";
} else {
return "女~~~";
}
})
let vm = new Vue({
el: "#app",
data: {
userList: [
{ id: 1, name: 'jacky', gender: 1 },
{ id: 2, name: 'peter', gender: 0 }
]
},
filters: { // 局部过滤器,只可以在当前vue实例中使用
genderFilter(val) {
if (val == 1) {
return "男";
} else {
return "女";
}
}
}
})
</script>
</body>
</html>
4.表单、复选框
https://www.runoob.com/vue2/vue-forms.html
4.1. 多选checkbox
虽然v-model指定了同个值,但是会收集成数组。演示:https://www.runoob.com/try/try.php?filename=vue2-form2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>单个复选框:</p>
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
<p>多个复选框:</p>
<input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
<label for="runoob">Runoob</label>
<input type="checkbox" id="google" value="Google" v-model="checkedNames">
<label for="google">Google</label>
<input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
<label for="taobao">taobao</label>
<br>
<span>选择的值为: {{ checkedNames }}</span>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
checked : false,
checkedNames: []
}
})
</script>
</body>
</html>
4.2. 单选radio
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="radio" id="runoob" value="Runoob" v-model="picked">
<label for="runoob">Runoob</label>
<br>
<input type="radio" id="google" value="Google" v-model="picked">
<label for="google">Google</label>
<br>
<span>选中值为: {{ picked }}</span>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
picked: 'Runoob'
}
})
</script>
</body>
</html>
4.3.下拉select
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<select v-model="selected" name="fruit">
<option value="">选择一个网站</option>
<option value="www.runoob.com">Runoob</option>
<option value="www.google.com">Google</option>
</select>
<div id="output">
选择的网站是: {{selected}}
</div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
selected: ''
}
})
</script>
</body>
</html>
5.修饰符
.lazy
在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >
.number
如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:
<input v-model.number="age" type="number">
这通常很有用,因为在 type=“number” 时 HTML 中输入的值也总是会返回字符串类型。
.trim
如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:
<input v-model.trim="msg">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id=app>
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg">
{{msg}}
<input v-model="age" type="number">
{{age}}
<input v-model.trim="msg">
{{msg}}
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
let vm=new Vue({
el: "#app",
data: {
age: 100,
msg: "hello"
}
});
</script>
</body>
</html>
6.组件化
在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面都自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同分拆分成立的组件,然后在不同页面就可以共享这些组件,避免重复开发。
在vue里,所有的vue实例都是组件
- 组件其实也是一个vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
- 不同的是组件不会与页面的元素绑定(所以不写el),否则就无法复用了,因此没有el属性。
- 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
- data必须是一个函数,不再是一个对象。
- 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了
下面的html内容是在说:
-
这个块跟下面的<div id="app">
对象绑定new Vue
- vue对象里指定了
属性,是指:标签里有子标签,’components
’:button-counter
代表有个组件叫buttonCounter
,可以填充标签buttonCounter
<button-counter>
Vue组件的使用
参考:
https://cn.vuejs.org/v2/guide/components.htmlhttps://www.runoob.com/vue2/vue-component.html
-
全局组件
参考:https://cn.vuejs.org/v2/guide/components-registration.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<button v-on:click="count++">我被点击了 {{count}} 次</button>
<counter></counter>
<counter></counter>
<counter></counter>
<counter></counter>
<counter></counter>
<hr/>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
// 定义一个名为 button-counter 的新组件
//1、全局声明注册一个组件
Vue.component('counter', {
data: function () { // data是函数
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' // 渲染的模板
});
new Vue({
el: "#app",
data: {
count: 1
}
});
</script>
</body>
</html>
局注册的组件可以用在其被注册之后的任何 (通过
new Vue
) 新创建的
Vue
根实例,也包括其组件树中的所有子组件的模板中。
这里还应该注解的是data那个属性,在组件中需要以函数的方式写\
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<button v-on:click="count++">我被点击了 {{count}} 次</button>
<counter></counter>
<counter></counter>
<counter></counter>
<counter></counter>
<counter></counter>
<hr/>
<button-counter></button-counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
// 定义一个名为 button-counter 的新组件
//1、全局声明注册一个组件
Vue.component('counter', {
data: function () { // data是函数
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' // 渲染的模板
});
//2、局部声明一个组件
const buttonCounter = {
template: `<button v-on:click="count++">我被点击了 {{count}} 次~~~</button>`,
data() {
return {
count: 1
}
}
};
new Vue({
el: "#app",
data: {
count: 1
},components: {
'button-counter': buttonCounter
}
});
</script>
</body>
</html>
7.生命周期钩子函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<span id="num">{{num}}</span>
<button @click="num++">赞!</button>
<h2>{{name}},有{{num}}个人点赞</h2>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
name: "张三",
num: 100
},
methods: {
show() {
return this.name;
},
add() {
this.num++;
}
},
beforeCreate() {
console.log("=========beforeCreate=============");
console.log("数据模型未加载:" + this.name, this.num);
console.log("方法未加载:" + this.show());
console.log("html模板未加载:" + document.getElementById("num"));
},
created: function () {
console.log("=========created=============");
console.log("数据模型已加载:" + this.name, this.num);
console.log("方法已加载:" + this.show());
console.log("html模板已加载:" + document.getElementById("num"));
console.log("html模板未渲染:" + document.getElementById("num").innerText);
},
beforeMount() {
console.log("=========beforeMount=============");
console.log("html模板未渲染:" + document.getElementById("num").innerText);
},
mounted() {
console.log("=========mounted=============");
console.log("html模板已渲染:" + document.getElementById("num").innerText);
},
beforeUpdate() {
console.log("=========beforeUpdate=============");
console.log("数据模型已更新:" + this.num);
console.log("html模板未更新:" + document.getElementById("num").innerText);
},
updated() {
console.log("=========updated=============");
console.log("数据模型已更新:" + this.num);
console.log("html模板已更新:" + document.getElementById("num").innerText);
}
});
</script>
</body>
</html>