一、计算属性
<div id="app">
<!-- 一般情况下写法 -->
<h1>{{firstname+lastname}}</h1>
<!-- 计算属性,如果属性经常修改,这个比firstname+lastname性能要好 -->
<h1>{{fullname}}</h1>
<!--逆序显示1个单词,每次要计算性能不好 -->
<h1>{{ word.split("").reverse().join("") }}</h1>
<!-- 节约性能 -->
<h1>{{reverseWord}}</h1>
<h1>循环偶数年龄</h1>
<ul>
<li v-for="item,index in oddStudents">
<h3>{{item.studentName}}</h3>
<h4>{{item.age}}----{{item.school}}</h4>
</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
firstname:"张",
lastname:"三",
word:"music",
students:[
{
studentName:"小明",
age:16,
school:"清华",
imgheader:"http://b-ssl.duitang.com/uploads/item/201510/24/20151024160112_uYtPB.jpeg"
},
{
studentName:"小黑",
age:17,
school:"北大"
},
{
studentName:"小红",
age:18,
school:"浙大"
},
{
studentName:"小红",
age:15,
school:"浙大"
}
]
},
computed:{
fullname:function(){
console.log(this)
//会将计算的结果进行缓存,只要this.firstname和lastname变量的内容不改变,就不会重新计算
return this.firstname+this.lastname
},
//节省性能
reverseWord:function(){
return this.word.split("").reverse().join("")
},
// 这样的话只有内容不改变,就不会在进行计算
oddStudents:function(){
let results = this.students.filter((item,i)=>{
// 年龄是偶数的数组
return item.age%2==0
})
return results
}
}
})
</script>
二、侦听器
<div id="app">
<h1>{{msg}}</h1>
<h1>{{reverseMsg}}</h1>
<ul>
<li v-for="item in arr">{{item}}</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
msg:"hello Vue",
arr:['小明','小红',"小黑"]
},
computed:{
reverseMsg:{
// 得到内容后颠倒
get:function(){
return this.msg.split("").reverse().join("")
},
// 如果通过后台修改数据加上这个才能颠倒
set:function(value){
//console.log(value)
this.msg = value.split("").reverse().join("")
}
}
},
watch:{
// 监听数据的改变
msg:function(val){
console.log("监听事件-------msg")
console.log(val)
},
// 监听数组的添加
arr:function(val){
console.log("监听事件-------arr")
this.msg = "监听事件-------arr"
console.log(val)
}
}
})
</script>
添加数组
三、设置样式
<style type="text/css">
.page{
width: 200px;
height: 200px;
background: skyblue;
display: none;
}
.active{
display: block;
}
</style>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- <div class="page"></div> -->
<!-- 通过对象的方式决定是否存在某个类 -->
<div class="page" :class="{active:isTrue}"></div>
<!-- 直接放置对象 -->
<div class="page" :class="styleObj"></div>
<!-- 放置数组 -->
<div class="page" :class="styleArr"></div>
<!-- 放置字符串 -->
<div class="page" :class="styleStr"></div>
<!-- 数组和对象混合和使用 -->
<div class="page" :class="styleArrObj"></div>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
isTrue:true,
// 放置对象
// col-lg-6需要加上引号告诉程序是字符串加上“”,因为‘-’在数组是是非法
styleObj:{active:true,laochen:true,"col-lg-6":true},
// 可直接用数组的方式进行添加和删除
// 放置数组
styleArr:['col-xs-12','red-bg'],
styleStr:"abc cba qwer",
//判断是否添加
styleArrObj:['abc',{active:false}]
},
})
</script>
菜单栏
<div id="app">
<div style="width: 100px;height: 100px;background: skyblue;"></div>
<!-- CSS内联样式变量拼接 -->
<div style="width: 100px;height: 100px;background: skyblue;"
:style="{ border: borderWidth+'px solid red',padding:paddingWidth+'px' }"></div>
<!-- CSS内联样式放置对象 -->
<div :style="styleObj"></div>
<!-- CSS数组的方式拼接 -->
<div :style="styleArr"></div>
</div>
<script type="text/javascript">
let app = new Vue({
el:"#app",
data:{
borderWidth:50,
paddingWidth:30,
styleObj:{
width:"200px",
height:"300px",
padding:"50px",
'background-color':'skyblue'
},
styleArr:[
{
width:"200px",
height:"300px",
padding:"50px",
'background-color':'skyblue'
},{
border:"30px solid yellow"
}
]
}
})
</script>
四、事件绑定
<div id="app">
<h1>点击次数:{{count}}</h1>
<!-- 可以使用表达式完成事件操作 -->
<button type="button" @click="count+=1">点击</button>
<!-- 获取事件对象 -->
<button @click="clickEvent">点击2</button>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
count:0
},
methods:{
clickEvent:function(event){
console.log(event)
console.log(this)
this.count++;
}
}
})
</script>
<body>
<div id="app">
<ul>
<!-- 点击后传值 -->
<li v-for="item,index in stars" @click="clickEvent(index,item,$event)">索引值:{{index}}----内容:{{item}}</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:"#app",
data:{
stars:['蔡徐坤','范冰冰','李晨']
},
methods:{
clickEvent:function(index,value,event){
console.log(index)
console.log(value)
console.log(event)
}
}
})
</script>
修饰符
https://cn.vuejs.org/v2/guide/syntax.html#%E4%BF%AE%E9%A5%B0%E7%AC%A6
<div id="app">
<!-- stop修饰符,阻止冒泡事件向上传递 -->
<div class="btnParent" @click="clickParent">
<!-- .stop,只会触发clickEvent按钮 -->
<button @click.stop="clickEvent">按钮</button>
</div>
<form action="" method="post">
<!-- 绑定输入框回车事件,同时绑定f1事件 -->
<input type="text" @keydown.enter.f1="searchWeather" name="username" v-model="city" id="" value="" />
<!-- 阻止默认事件 -->
<input @click.prevent="searchWeather" type="submit" value="提交"/>
</form>
<div id="weather">
<h1>{{tmp}}</h1>
<h3>{{brief}}</h3>
</div>
<h1>只触发一次修饰符</h1>
<button type="button" @click.once='onceEvent'>只触发一次按钮</button>
<!-- 加上exact,只能按ctrl,不能按其他才能触发 -->
<button type="button" @click.ctrl.exact="ctrlEvent">按住ctrl事件</button>
</div>
<script type="text/javascript">
// 配置按键的自定义修饰符
Vue.config.keyCodes.f1 = 112
var app = new Vue({
el:"#app",
data:{
count:0,
city:"广州",
tmp:"",
brief:""
},
methods:{
clickEvent:function(event){
console.log("clickEvent")
},
clickParent:function(){
console.log("clickParent")
},
searchWeather:async function(){
console.log("查询天气")
console.log(this.city)
let httpUrl = `https://free-api.heweather.net/s6/weather/now?location=${this.city}&key=3c497450d8e44c5280421ceaba1db581`
let res = await fetch(httpUrl)
let result = await res.json()
// 等待拿到数据
console.log(result)
let now = result.HeWeather6[0].now;
this.tmp = now.tmp;
this.brief = now.cond_txt;
// 从得到的数据里找到数组里的数据
},
onceEvent:function(){
console.log('只触发一次')
},
ctrlEvent:function(){
console.log('ctrlEvent')
}
}
})
</script>
绑定内容
https://cn.vuejs.org/v2/guide/forms.html
<div id="app">
<h2>{{username}}</h2>
<h1>单行文本输入框</h1>
<!--具有双向绑定, 输入框enter健会改变username的内容 -->
<!-- lazy修饰符只有离开焦点或者按enter健,trim修饰符去掉空格 -->
<input type="text" name="username" v-model.lazy.trim="username" value="" />
<h1>多行文本输入框</h1>
<h1>复选框:选择喜欢的水果</h1>
<span v-for="item in fruits">
{{item}}
<input type="checkbox" name="fruit" v-model="checkFruits" :value="item" />
</span>
<!-- 输出点击的数组 -->
<h2>{{checkFruits}}</h2>
<h1>单选框:选择最喜欢的水果</h1>
<span v-for="item in fruits">
{{item}}
<input type="radio" name="zfruit" v-model="radioFruits" :value="item" />
</span>
<!-- 输出点击的数组 -->
<h2>{{radioFruits}}</h2>
<h1>选项框:选择你居住的城市</h1>
<select v-model="chooseCity">
<option disabled value="">请选择</option>
<option v-for="item in citys" :value="item">{{item}}</option>
</select>
<!-- 输出点击的数组 -->
<h3>{{chooseCity}}</h3>
<h1>选项框:选择你喜欢的城市</h1>
<!-- 按下ctrl可以多选 -->
<select v-model="moreCity" multiple="multiple">
<option v-for="item in citys" :value="item">{{item}}</option>
</select>
<!-- 输出点击的数组 -->
<h3>{{moreCity}}</h3>
<h1>将字符串变为数字获取</h1>
<input type="text" name="age" v-model.number="age" value="" />
</div>
<script type="text/javascript">
let app = new Vue({
el:"#app",
data:{
username:"小明",
fruits:['苹果','雪梨',"香蕉","葡萄"],
checkFruits:[],
radioFruits:"",
citys:['北京',"上海","深圳","广州"],
chooseCity:"",
moreCity:[],
age:16
},
watch:{
age:function(val){
console.log(val)
}
}
})
</script>
五、过渡动画
通过绑定属性操作动画
六、生命周期
七、组件传值
通过props传值
<div id="app">
<ul>
<!-- 从父组件传值到子组件 -->
<product-com v-for="item,index in proList" :product="item"></product-com>
</ul>
</div>
<script type="text/javascript">
//产品组件
Vue.component("product-com",{
props:['product'],
template:`<li>
<h3>产品名称:{{product.title}}</h3>
<h4>产品描述:{{product.brief}}</h4>
<p>产品价格:{{product.price}}</p>
</li>`,
data:function(){
return {
title:"三只松鼠"
}
}
})
//根组件
let app = new Vue({
el:"#app",
data:{
proList:[
{
title:"产品1",
price:"10",
brief:"产品描述1"
},
{
title:"产品2",
price:"20",
brief:"产品描述2"
},
{
title:"产品3",
price:"30",
brief:"产品描述3"
},{
title:"产品4",
price:"40",
brief:"产品描述4"
}
]
}
})
</script>
父传子传值
<div id="app">
<ul>
<!-- 从父组件传值到子组件 -->
<!-- 静态属性 -->
<!-- 没":" -->
<school school-name="清华北大"></school>
<!-- 动态属性 -->
<!-- 加上'',会变成字符串,没有是错的 -->
<school :school-name="'上海浙大'"></school>
<!-- 动态属性 -->
<school :school-name="schoolList[0]"></school>
<!-- 循环传值组件 -->
<!-- 浏览器会提示加上key,加上'abc'后的话表示独一无二 -->
<school v-for="item,index in schoolList" :key="'abc'+index" :index='index' :school-name="item"></school>
</ul>
</div>
<script type="text/javascript">
//产品组件
Vue.component("school",{
props:['schoolName','index'],
template:`<li>
<h3>{{index}}-学校名称:{{schoolName}}</h3>
</li>`
})
//根组件
let app = new Vue({
el:"#app",
data:{
schoolList:['sxt','czbk','xmg']
}
})
</script>
</body>
子传父(通过点击事件吧学校名称传到父级)
<div id="app">
<ul>
<!-- 从父组件传值到子组件 -->
<!-- 循环传值组件 -->
<!-- @cschool,监听this.$emit('cschool',schoolName) -->
<school v-for="item,index in schoolList" @cschool='changeEvent' :key="'abc'+index" :index='index' :school-name="item"></school>
</ul>
<h2>选中的学校是:{{chooseSchool}}</h2>
</div>
<script type="text/javascript">
//产品组件
Vue.component("school",{
props:['schoolName','index'],
template:`<li>
<h3>{{index}}-学校名称:{{schoolName}}</h3>
<button @click="chooseEvent(schoolName)">选择学校</button>
</li>`
methods:{
chooseEvent:function(schoolName){
console.log(schoolName)
//想要将子元素的数据传递给父元素,需要自定义触发事件,实现数据的传值
// console.log(this)
// 触发一个事件名称叫做cShool的事件,把测试cshool赋值到schoolName,触发
// @cschool='changeEvent事件
this.$emit('cschool',schoolName)
}
}
})
//根组件
let app = new Vue({
el:"#app",
data:{
schoolList:['清华','北大','浙大',"中大"],
chooseSchool:""
},
methods:{
// 通过点击@cschool='changeEvent,获取由schoolName获取的函数cshool的值data
changeEvent:function(data){
// error
// console.log(schoolName)
console.log("触发学校选择事件")
this.chooseSchool = data
}
}
})
</script>
八、组件传值升级版
添加:action='changeEvent’进行传值
<div id="app">
<ul>
<!-- 从父组件传值到子组件 -->
<!-- 循环传值组件 -->
<!--
因为父元素的方法可以直接修改父元素的数据
所以将父元素的方法传递给子元素,
然后由子元素进行调用,从而修改父元素的数据
-->
<!-- :action动态方法 -->
<school v-for="item,index in schoolList" :action='changeEvent' :key="'abc'+index" :index='index' :school-name="item"></school>
</ul>
<h2>选中的学校是:{{chooseSchool}}</h2>
</div>
<script type="text/javascript">
//产品组件
Vue.component("school",{
props:['schoolName','index','action'],
template:`<li>
<h3>{{index}}-学校名称:{{schoolName}}</h3>
<button @click="chooseEvent(schoolName)">选择学校</button>
</li>`,
methods:{
chooseEvent:function(schoolName){
console.log(schoolName)
console.log(this.action)
console.log(this)
this.action(schoolName)
}
}
})
//根组件
let app = new Vue({
el:"#app",
data:{
schoolList:['清华','北大','浙大',"中大"],
chooseSchool:""
},
methods:{
changeEvent:function(data){
//console.log("触发学校选择事件")
console.log(this)
this.chooseSchool = data
}
}
})
</script>
通过this里面$parent修改数据
<div id="app">
<ul>
<school v-for="item,index in schoolList" :key="'abc'+index" :index='index' :school-name="item"></school>
</ul>
<h2>选中的学校是:{{chooseSchool}}</h2>
</div>
<script type="text/javascript">
//产品组件
Vue.component("school",{
props:['schoolName','index','action'],
//在视图直接调用父元素方法
template:`<li>
<h3>{{index}}-学校名称:{{schoolName}}</h3>
<button @click="chooseEvent(schoolName)">选择学校</button>
</li>`,
methods:{
chooseEvent:function(schoolName){
// console.log(schoolName)
// console.log(this)
// //组件可以通过$parent属性找到父元素的vue对象
this.$parent.changeEvent(schoolName)
}
}
})
//根组件
let app = new Vue({
el:"#app",
data:{
schoolList:['清华','北大','浙大',"中大"],
chooseSchool:""
},
methods:{
changeEvent:function(data){
this.chooseSchool = data
}
}
})
</script>
直接使用$parent方法
<div id="app">
<ul>
<school v-for="item,index in schoolList" :key="'abc'+index" :index='index' :school-name="item"></school>
</ul>
<h2>选中的学校是:{{chooseSchool}}</h2>
</div>
<script type="text/javascript">
//产品组件
Vue.component("school",{
props:['schoolName','index','action'],
//在视图直接调用父元素方法
template:`<li>
<h3>{{index}}-学校名称:{{schoolName}}</h3>
<button @click="$parent.changeEvent(schoolName)">选择学校</button>
</li>`,
//根组件
let app = new Vue({
el:"#app",
data:{
schoolList:['清华','北大','浙大',"中大"],
chooseSchool:""
},
methods:{
changeEvent:function(data){ vv
//console.log("触发学校选择事件")
console.log(this)
this.chooseSchool = data
}
}
})
</script>
直接在数组里使用$parent
template:`<li>
<h3>{{index}}-学校名称:{{schoolName}}</h3>
<button @click="$parent.chooseSchool = schoolName">选择学校</button>
</li>`,
使用this里面$root(不建议使用,可能会造成代码混乱)
Vue.component("school",{
props:['schoolName','index','action'],
template:`<li>
<h3>{{index}}-学校名称:{{schoolName}}</h3>
<button @click="$root.changeEvent(schoolName)">选择学校</button>
</li>`,
methods:{
chooseEvent:function(schoolName){
console.log(schoolName)
console.log(this)
}
}
})
let app = new Vue({
el:"#app",
data:{
schoolList:['清华','北大','浙大',"中大"],
chooseSchool:""
},
methods:{
changeEvent:function(data){
// console.log(this)
this.chooseSchool = data
}
},
mounted() {
console.log(this)
}
})
九、v-model
数据绑定
<div id="app">
<input type="text" v-model="username" value="" />
//给获取username的值,赋值在value
<input type="text" @input="username = $event.target.value" :value="username" name="" id="" />
<h3>{{username}}</h3>
</div>
数组绑定
<body>
<div id="app">
// 绑定child-input ,监听事件changeEvent
<input-com :username='username' @child-input='changeEvent'></input-com>
//不需要触发changeEvent事件
//绑定child-input, 监听里面的$event.target.value
<input-com :username='username' @child-input='username=$event'></input-com>
<h3>{{username}}</h3>
</div>
<script type="text/javascript">
Vue.component('input-com',{
props:['username'],
// 绑定child-input
template:`<input type="text" @input="$emit('child-input',$event.target.value)" :value="username" />`,
})
let app = new Vue({
el:"#app",
data:{
username:""
},
methods:{
changeEvent:function(data){
this.username = data
}
}
})
</script>
vue自带input
<div id="app">
<input-com :username='username' @input='username=$event'></input-com>
<input-com v-model="username"></input-com>
<h3>{{username}}</h3>
</div>
Vue.component('input-com',{
props:['username'],
template:`<input type="text" @input="$emit('input',$event.target.value)" :value="username" />`,
})
原生绑定
<body>
<input type="text" name="" id="username" value="" />
<h1></h1>
<script type="text/javascript">
let inputDom = document.querySelector("#username")
// 监听输入变化
inputDom.oninput = function(){
document.querySelector("h1").innerHTML = inputDom.value
}
</script>
十、插槽
组件中,放置内容的两种发法
<。slot></slot。>,第二个组件只有加上才能显示{{content}}
<body>
<div id="app">
//里面的内容变量只跟父元素有关,所以{{abc}}不会显示
<alert-com :html='content'>{{abc}}</alert-com>
<alert-com1>
<p>小心陈老师,{{content}},{{abc}}</p>
</alert-com1>
</div>
<script type="text/javascript">
Vue.component('alert-com',{
props:['html'],
template:`
<div class="alert">
<h1>温馨提示</h1>
<div class="content">
{{html}}
</div>
</div>
`
})
Vue.component('alert-com1',{
template:`
<div class="alert">
<h1>温馨提示</h1>
<div class="content">
<slot></slot>
</div>
</div>
`,
data:function(){
return {
abc:"abc123"
}
}
})
let app = new Vue({
el:"#app",
data:{
content:"小心熊出没",
}
})
</script>
</body>
动态组件
<body>
<div id="app">
<div id="content">
<!-- is="com1",静态属性 -->
<component :is="com"></component>
</div>
<button @click="chooseContent(1)">首页</button>
<button @click="chooseContent(2)">列表</button>
<button @click="chooseContent(3)">新闻</button>
<button @click="chooseContent(4)">个人</button>
</div>
<script type="text/x-template" id="laochen">
<div>
<h1>首页内容</h1>
<p>Hello hello hello vue</p>
</div>
</script>
<script type="text/javascript">
let com1 = Vue.component("index-com",{
// name:'index',
template:'#laochen'
})
let com2 =Vue.component("list-com",{
template:'<div><h1>列表内容</h1><p></p></div>'
})
let com3 =Vue.component("news-com",{
template:'<h1>新闻内容</h1>'
})
let com4 =Vue.component("me-com",{
template:'<h1>个人中心内容</h1>'
})
let app = new Vue({
el:"#app",
data:{
com:com1
},
methods:{
chooseContent:function(id){
console.log(id)
console.log(this)
//通过获取id,选择注册好的组件,修改this里面的compons
this.com = this.$options.components['com'+id]
}
},
components:{
com1,com2,com3,com4
}
})
</script>
</body>