vue.js
[vuejs挂载点,模板与实例的关系]
<body>
<div id='root'>
<h1>{{msg}}</h1>
</div>
<script>
new Vue({
el:'#root',
data:{
msg:'hello world'
}
})
</script>
</body>
挂载点:element对应的标签
上面的html中{{msg}}去掉
<div id='root'></div>
这个标签就称之为vue实例的挂载点,因为下面的el,也就是element正好与上面的标签的id对应的上
模板:挂载点内部的内容
<h1>{{msg}}</h1>
这个就是模板,模板也可以有多种方式
new Vue({
el:'#root',
template:'<h1>{{msg}}</h1>',
data:{
msg:'hello world'
}
})
这种写在实例里面也可以,所以模板就是挂载点内部的内容,模板可以写在挂载点内部,也可以写在实例里面template属性里面
首先我们知道vue中有很多自定义指令,以v- 开头,例如:v-text,v-bind,v-model, v-if,等
在这些指令中,部分指令之间是很容易被混淆,所以今天决定自己总结一下以下几个相似指令之间的异同:
<!--区别:v-text打印出来包含标签 v-html不包含标签-->
<div class="root" v-text="number"></div>
<div class="root1" v-html="number"></div>
<!--点击事件用v-on方法-->
<div id="root" v-on:click="tomyclick">{{number}}</div>
<!--点击事件用@方法-->
<div id="root1" @click="tomyclick">{{number}}</div>
<script>
new Vue({
el:".root",
data:{
number:"<h1>这是v-text方法</h1>"
},
})
new Vue({
el:".root1",
data:{
number:"<h1>这是v-html方法</h1>"
},
})
new Vue({
el:"#root",
data:{
number:"这是v-on:click方法"
},
methods:{
tomyclick : function(){
this.number = "点击之后的效果用v-on方法"
}
}
})
new Vue({
el:"#root1",
data:{
number:"这是v-on:click方法"
},
methods:{
tomyclick : function(){
this.number = "点击之后的效果用@方法"
}
}
})
</script>
</body>
image.png
image.png
image.png
1、属性绑定
v-bind :
<div id="root">
<div v-bind:title="title">hello world</div>
</div>
<script>
new Vue({
el:"#root",
data:{
title:"this is hello world"
}
})
</script>
v-bind可以缩写为“:”
即<div v-bind:title="title">hello world</div>可以写为
<div :title="title">hello world</div>
单向绑定:数据决定页面的显示,但页面不能决定数据的内容
双向绑定:数据决定页面的显示,但页面也能修改数据的内容
用v-model实现双向绑定
<div id="root">
<input type="text" v-model:value="content">//当修改input的值时,content的值也会做相应修改
<div>{{content}}</div>
</div>
<script>
new Vue({
el:"#root",
data:{
content: "this is content"
},
})
</script>
image.png
2、vue中的计算属性和侦听器
2.1计算属性computed:一个属性通过其他属性计算而来
fullName由firstName和lastName计算而来.
当firstName和lastName不发生变化时,fullName不会重新计算而是调用缓存值,提高了程序效率。
<div id="root">
姓:<input type="text" v-model:value="firstName">
名:<input type="text" v-model:value="lastName">
<div>{{fullName}}</div>
<div>{{count}}</div>
</div>
<script>
new Vue({
el: "#root",
data: {
firstName: '',
lastName: '',
},
//计算属性
computed:{
fullName: function () {
return this.firstName+" "+this.lastName
}
},
})
</script>
image.png
2.1侦听器watch:监听某个数据的变化,一旦数据发生变化,就可以在侦听器中进行逻辑计算
<div id="root">
姓:<input type="text" v-model:value="firstName">
名:<input type="text" v-model:value="lastName">
<div>{{fullName}}</div>
</div>
<script>
new Vue({
el: "#root",
data: {
firstName: '',
lastName: '',
fullName: ''
},
watch:{
firstName:function () {
this.fullName=this.firstName+" "+this.lastName;
},
lastName: function () {
this.fullName=this.firstName+" "+this.lastName;
}
}
})
</script>
image.png
计算属性computed的getter和setter:
<div id="root">
{{fullName}}
</div>
<script>
var vm=new Vue({
el: "#root",
data: {
firstName: 'Dell',
lastName: 'Lee',
fullname: 'Dell Lee'
},
computed:{
fullName:{
get: function () {
return this.firstName+" "+this.lastName
},
set: function (value) {
var arr=value.split(" ");
this.firstName=arr[0];
this.lastName=arr[1];
}
}
}
})
image.png
[vuejs里面v-if,v-show和v-for]
<div id='root'>
<div v-if='show'>helle world</div>
<button @click='handleClick'>toggle</button>
</div>
<script>
new Vue({
el:'#root',
data:{
show:true
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
})
</script>
v-if,里面这个show是个变量,如果是true就是显示,如果是false就不显示,这里是移除了dom
<div id='root'>
<div v-show='show'>helle world</div>
<button @click='handleClick'>toggle</button>
</div>
<script>
new Vue({
el:'#root',
data:{
show:true
},
methods:{
handleClick:function(){
this.show = !this.show;
}
}
})
</script>
v-show,把v-show替换掉v-if,表现形式一样,但是和v-if不同的是,v-show只是将dom隐藏,显示,并没有移除dom,只是把display的样式变了
如果显示的频率大,v-show比v-if要性能高一些,因为不会去销毁dom,和创建dom,如果显示的频率不是那么大,只要一次显示隐藏,那么v-if是更好的选择
<div id='root'>
<ul>
<li v-for='item of list' :key='item'>{{item}}</li>
</ul>
</div>
<script>
new Vue({
el:'#root',
data:{
list:[1,2,3]
}
})
</script>
当你给元素标签加key值得时候, vue会知道它是页面上唯一的一个元素,如果两个key不一样,vue不会复用
v-for,当某个数据需要循环显示的时候,可以用v-for,这里需要注意加:key,可以提升性能,但是这个item变量要是唯一的,如果数组是[1,1,3],这个item就不能作为key值,需要将
v-for='item of list'
改成
v-for='(item,index) of list',
将索引index作为key值,这样是唯一的,但是index作为key值,在对列表排序等操作的时候可能存在问题
一个简单的todolist
<script type="text/javascript" src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="root">
<div>
<input v-model = "inputValue"/>
<button @click = "handleSubmit">提交</button>
</div>
<ul>
<li v-for = "(item , index) of list" :key = "index">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el:"#root",
data:{
inputValue:'999',
list:[]
},
methods:{
handleSubmit:function(){
this.list.push(this.inputValue),
this.inputValue = ''
}
}
})
</script>
运用组件化的概念进行整改
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>vue学习</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id = "app">
<input type="text" v-model = "interValue"/>
<button v-on:click = "handleBtnClick">提交</button>
<ul>
<!-- <li v-for = "item in list">{{item}}</li> -->
<todo-item v-bind:content="item" v-for = "item in list"></todo-item>
</ul>
</button>
</div>
<script>
Vue.component("TodoItem",{
props : ["content"],
template : "<li>{{content}}</li>",
})
var app = new Vue ({
el : '#app',
data :{
list : [],
interValue : ''
},
methods : {
handleBtnClick : function(){
this.list.push(this.interValue)
this.interValue = ''
}
}
})
setTimeout(function() {
app.$data.content = '我要改变'
// app.content = '我要改变';
}, 2000)
</script>
</body>
</html>
需要注意四点就是
1.Vue.component 这样使用的是全局组件
2.TodoItem 到节点运用就成了todo-item
3.v-bind:content="item" 父组件把值传给子组件
- props : ["content"]这样接受
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>vue学习</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id = "app">
<input type="text" v-model = "interValue"/>
<button v-on:click = "handleBtnClick">提交</button>
<ul>
<!-- <li v-for = "item in list">{{item}}</li> -->
<todo-item v-bind:content="item"
v-bind:index="index"
v-for = "(item, index) in list"
@delete = "handleItemDelete"
></todo-item>
</ul>
</button>
</div>
<script>
// Vue.component("TodoItem",{
// props : ["content"],
// template : "<li>{{content}}</li>",
// })
var TodoItem = {
props : ["content","index"],
template : "<li @click = 'handleItemClick'>{{content}}</li>",
methods : {
handleItemClick : function(){
this.$emit('delete',this.index)
},
}
}
var app = new Vue ({
el : '#app',
components :{
TodoItem : TodoItem,
},
data :{
list : [],
interValue : ''
},
methods : {
handleBtnClick : function(){
this.list.push(this.interValue)
this.interValue = ''
},
handleItemDelete : function(index){
this.list.splice(index,1)
}
}
})
setTimeout(function() {
app.$data.content = '我要改变'
// app.content = '我要改变';
}, 2000)
</script>
</body>
</html>
需要注意四点就是
1var TodoItem 这样使用的是局部组件,创建了一对象
2.components :{
TodoItem : TodoItem,
},
把局部组件注册到根实例里面。
3.template : "<li @click = 'handleItemClick'>{{content}}</li>", 这里是列表cell添加点击事件
4.@delete = "handleItemDelete" 这里父组件在创建子组件的时候进行监听
- this.开头的都是vue的实例属性跟实例方法
生命周期函数就是vue的实例在某一个时间点会自动执行的函数。生命周期函数并不在methosd,单独写在实例里。
init-->beforeCreate -->created--> beforeMount -->mounted -->beforeDestroy -- >destroyed
image.png
image.png image.png
大图解析,
image.png
v-xxx=""后面的字符串是js表达式。可以+操作
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
reversedMessage: function () {
// `this` 指向 vm 实例
return xxxx
}
}
});
关于计算属性优点就是他能缓存,提高性能,页面重新渲染的,计算属性依赖的值给没有发生改变,这个时候计算属性就不会计算,提高性能.用方法的形式也可以实现计算的结算,但是页面只要渲染方法就会调用,用监听器也可以实现这个功能,也会有缓存。
image.png
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="text/html; charset=utf-8" />
<title>Vue</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">{{fullName}}</div>
<script>
var vm = new Vue({
el : '#root',
data :{
firstName : 'Dell',
lastName : 'Lee'
},
computed :{
fullName : {
get :function (){
return this.firstName + " " +this.lastName
},
set :function(value){
console.log(value);
var array = value.split(" ");
this.firstName = array[0];
this.lastName = array[1];
}
}
}
})
</script>
</body>
</html>
计算属性跟set跟get方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="text/html; charset=utf-8" />
<title>Vue</title>
<script src="./vue.js"></script>
<style>
.acivated{
color: red
}
</style>
</head>
<body>
<div id="root" :class = "[acivated]" @click = "handleClick">{{content}}</div>
<script>
var vm = new Vue({
el : '#root',
data : {
content : '我是内容',
acivated : ''
},
methods : {
handleClick : function(){
this.acivated = this.acivated === "acivated" ? "" : "acivated";
}
}
})
</script>
</body>
</html>
知识点
1.:class = "[acivated]" 这里主要是表示class这块的东西,这是一个数组可以添加多个,样式就有这个数组里面的东西决定。
image.png
同样的东西,这里是style的用法,可以在 :style = "[styleObj {fontSize : '20px'}]"
如果是按照数组下标的方法进行操作数组,页面没有及时渲染,想要及时渲染,要用系统提供的七个方法。
push pop shift unshift splice sort reverse
当然你也可以直接替换数据的引用地址,这样也能改变渲染。
还有一个方法就是用set修改,也可数据改变之后页面也改变
Vue.set(vm.userInfo,1,5)
一个比较重要的模板占位符 template 可以包裹 元素,但是 渲染的时候并不会真正的渲染到页面中。
image.png image.png
直接修改vm.userInfo.name = "Dell Lee"可以在页面中立刻渲染
但是想添加 vm.userInfo.address = "beijing" 这样数据是添加进去了,但是不能立即渲染。
想立即改变要直接改变数据引用地址,就是直接改好数据,直接把引用引到新数据下面。
其实用set方法修改,也能让数据改变之后页面也立刻改变。
例如 Vue.set(vm.userInfo,"address","beijing")
vue遇到问题解析
1.有些时候自定义的标签在使用起来发现出问题了,table--> tbody -->tr就是tbody下面必须是tr标签,要不就就会出问题,这个时候要做的是用 is=“”来处理
image.png
2.子组件的data必须是一个函数不能是一个对象.
image.png
3,添加ref 添加引用,便于操作dom节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="text/html; charset=utf-8" />
<title>Vue</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<couter ref = "one" @change = "handeleChange"></couter>
<couter ref = "two" @change = "handeleChange"></couter>
<div>{{total}}</div>
</div>
<script>
Vue.component('couter',{
template : '<div @click = "handleClick">{{number}}</div>',
data :function(){
return {
number : 0
}
},
methods :{
handleClick : function(){
this.number ++;
this.$emit('change')
}
}
})
var vm = new Vue({
el : '#root',
data : {
total : 0
},
methods : {
handeleChange : function(){
this.total = this.$refs.one.number + this.$refs.two.number
}
}
})
</script>
</body>
</html>
涉及到父子组件传值的概念
单向数据流:父组件给子组件传递参数,传递过得参数可以随意修改,但是子组件不能修改父组件传递过来的内容。原因传递过来的数据如果是引用数据类型的数据,如果你修改了 数据就是修改了原始数据。
校验器
image.png
@click.nataive 这个就是监听的原生的click事件,并非自定义的
非父子组件进行传值
image.png
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
var this_ = this 是因为作用域发生了变化,有一个function,this变成了function了
,要保存一下
插槽语法,方便插入dom元素,还可以定义默认内容 ,还能给插槽给一个name,这样可以对应,根据name变换插槽
image.png
动态组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 动态组件</title>
<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<button @click='toShow'>点击显示子组件</button>
<!----或者<component v-bind:is="which_to_show" keep-alive></component>也行----->
<keep-alive>
<component v-bind:is="which_to_show" ></component>
</keep-alive>
</div>
<script>
// 创建根实例
new Vue({
el: '#app',
data:{
which_to_show:'first'
},
methods:{
toShow:function(){
var arr = ["first","second","third"];
var index = arr.indexOf(this.which_to_show);
if(index<2){
this.which_to_show = arr[index+1];
}else{
this.which_to_show = arr[0];
} console.log(this.$children);
}
},
components:{
first:{
template:'<div>这是子组件1<div>'
},
second:{
template:'<div>这是子组件2<div>'
},
third:{
template:'<div>这是子组件3<div>'
},
}
})
</script>
</body>
</html>
image.png
v-once 指令,可以让把组件第一次被渲染之后会放到内存里面
image.png image.png
image.png
这个东西很有意思,这边整体解释一下动画的东西,首先就是fade-enter 跟fade-enter-active在动画开始的第一帧就已经存在,然后第二帧的时候 fade-enter 被干掉,增加fade-enter-to ,到结束之后这个时候fade-enter-active,fade-enter-to被干掉。与opacity:0这个被去掉,恢复原有的默认属性,为1.此时,监听到opacity变化,fade-enter-active开始运行,会做一个渐变。