Vue基础(一)
前言
重新撸了一遍vue官网(到组件部分), 结合视频(慕课网得去乃儿网开发vue2.5),对vue简单基础用法根据官方文档的顺序,自己整理一下,
为什么使用Vue
结合资料与个人理解:在传统开发中,使用js来写页面 我们总是会大量的操作dom,拿代码举例
let asia_EA = document.getElementsByClassName("asia_extract_alert")[0];
let asia_eah = document.getElementsByClassName("asia_ea_header")[0];
let asia_dm = document.getElementsByClassName("asia_detialM")[0];
let asia_em = document.getElementsByClassName("asia_eam_main")[0];
let img = asia_eah.getElementsByTagName("img")[0];
let freetimes = document.getElementsByClassName("asia_tandi")[0].getElementsByTagName("span")[0].getElementsByTagName("font")[0];
let integral = document.getElementsByClassName("asia_tandi")[0].getElementsByTagName("span")[1];
根据ajax返回的值,改变页面上元素的innerText 那么在这之前我需要获取许许多多得对象,然后再改变.大量的逻辑都是通过js来写,这可以理解为mvp模式,我们在写的时候总是关注v层p层 很少关注M层,而使用了vue这种前端框架(mvvm)模式,
<div>{{content}}</div>
<div>{{content}}</div>
<div>{{content}}</div>
<div>{{content}}</div>
vue.js作为我们得vm层,他来负责把m层映射到v层,我们把注意力放到m层,不直接操作dom,我们只改变数据,这样会减少许多代码,提高效率.
Vue实例
每一个new Vue() 都是一个根实例,而Vue.component其实也是一个Vue实例,在根实例中data可以直接是一个对象,而在组件中data必须是一个带有返回值的函数,
<div id="app">
<div>{{content}}</div>
<child></child>
</div>
<script>
Vue.component('child',{
data () {
return {
brother:'destroy',
}
},
template:'<div>{{brother}}</div>'
})
var app = new Vue({
el:"#app",
data: {
content:'hellow world',
}
})
</script>
模板语法
插值表达式{{content}},在v-xxx=" "这种语法中,在 " " 里面得内容都是一个表达式(省略this),你可以写一个简单判断,加减法,但不要超过一句
<div id="app">
<div>{{content}}</div>
<div v-text="content"></div>
<div v-html="createSpan"></div>
<div v-if="type === true">刚才来了个暴躁老姐</div>
<div @click="giveYou">点我老哥</div>
<a href="" :href="'###'"></a>
<div v-for="item in testList">{{item}}</div>
</div>
<script>
var app = new Vue({
el:"#app",
data: {
content:'hellow world',
createSpan:'<span>暴躁老姐跟人家聊了3个小时才走,很烦</span>',
type:true,
testList:['1','2','3','4']
},
methods: {
giveYou:function(){
console.log("giveYou")
}
}
})
</script>
计算属性和监听器
之所以使用computed和watch: 当我们使用methods改变页面内容的时候,与其无关得内容改变methods也会再次执行,而计算属性和监听器 如果改变得内容跟她们所监听得无关,他会在直接从内存中拿值,在特定方面使用会节省效率
<div id="app">
<div>{{comContent}}</div>
<div>{{myName}}</div>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
content: 'hellow world',
myName: "red"
},
computed: {
comContent: {
get: function () {
return this.myName + '.......' + this.content;
},
set: function (value) {
let names = value.split(' ')
this.myName = names[0]
this.content = names[names.length - 1]
}
}
// comContent: function () {
// return this.myName + '.......' + this.content;
// }
},
watch: {
myName:function(){
this.content = 'myName变了';
}
},
methods: {
giveYou: function () {
console.log("giveYou")
}
}
})
</script>
计算属性有两个方法 get set, 默认(直接写个function)就是get,如果我们不写set方法,给计算属性赋值的时候会警告没有set方法.
Class与style的绑定
class绑定 基本就是 对象结构与数组结构,其中数组结构可以跟对象结构结合使用.
style绑定也是这样 只不过对象里面写法跟写css相同
<div id="app">
<!-- 对象形式 class名 red, 根据 isRed里面的布尔表达式判断red是否绑定到class上 -->
<div :class="{red:isRed}">{{content}}</div>
<!-- 数组形式 class名 就是oooo里面所存在的变量,直接写'backgrounD'代表class名就是这个字符串-->
<div :class="[oooo,'backgrounD']">{{myName}}</div>
<!-- 数组形式 数组里面也可以写对象,规则跟对象形式一样-->
<div :class="[{oooo:isAquamarine},'backgrounD']">{{myName}}</div>
<!-- 行内样式 直接绑定一个对象 对象格式跟你写css的形式是一模一样得 -->
<div :style="styObj">{{content}}</div>
<!-- 行内样式 也可以写成数组形式,或者直接写样式也可以 -->
<div :style="[styObj,{background:'#000000'}]">{{content}}</div>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
content: '你好 明天',
myName: 'red',
isRed: true,
isAquamarine: false,
oooo: 'oooo',
styObj:{
color:'#ffcc00',
}
},
})
</script>
条件渲染
v-if : 会改变dom 如果为 false,会在文档中删除,反之会添加到文档中,
v-show 紧紧是控制display的显示于隐藏
<div id="app">
<!-- v-show只是改变css 而 v-if会删除dom和添加dom 如果紧紧控制静态资源的显示与隐藏,直接用v-show就好了-->
<div v-if="show">{{content}}</div>
<div v-show="!show">{{myName}}</div>
<!-- v-if指定也可以写if-else 但是必须连贯的 否则无效 -->
<div v-if="fuck === 'a'">{{content}}</div>
<div v-else-if="fuck === 'b'">{{myName}}</div>
<div v-else>{{content+myName}}</div>
<!-- 当我们切换模板的时候 如果使用了相同元素,如input并不会呗替换掉,如果想让他们不同 则给他添加key属性即可 -->
<template v-if="bone === 'a'">
<label>{{content}}</label>
<input type="text" key="'wodetian'">
</template>
<template v-else-if="bone === 'b'">
<label>{{myName}}</label>
<input type="text" key="'wodetian2'">
</template>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
content: '你好 明天',
myName: 'red',
show: false,
fuck: 'c',
bone: 'b',
},
})
</script>
列表渲染
v-for: 可以循环对象与数组,值得一提的是key一定是唯一的 尽量不要使用index作为key
对象 v-for="(item, index) in list" :key="index"
数组 v-for="(item,key, index) in userInfo" :key="key"
当我们对对象,或数组 进行添加删除的时候, 要使用变异方法或者$set这种形式,因为Vue 不能检测对象属性的添加或删除,
如 数组的下角标形式 list[x] = 'xxx' 如果当前数组没有x 这样是不行得,它确实改变了对象,但是视图并未更新,list.length = 'newLength',同上, userInfo.xxx = ''xxx"同上
变异方法: push,pop,shift,unshift,splice,sort,reverse,
set方法: Vue.set(app.list,0,1000); app.$set(app.userInfo,'hehe','呵呵哒');
<div id="app">
<!-- 循环数组 key一定是唯一的 尽量不要使用index作为key-->
<div v-for="(item, index) in list" :key="index">
{{item+'_____'+ index}}
</div>
<!-- 循环对象 -->
<div v-for="(item,key, index) in userInfo" :key="key">
{{item+'_____'+key+'_____'+index}}
</div>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
content: '你好 明天',
myName: 'red',
list: [1, 2, 3, 45, 6, 7, 8, 9],
userInfo: {
name: 'red',
age: '24',
address: '火星',
}
},
})
Vue.set(app.list,0,1000);
app.$set(app.userInfo,'hehe','呵呵哒');
</script>
事件处理
由于紧紧是自学.并未具体应用到项目中,所以紧紧停留在,绑定个方法阶段,事件修饰符什么的也没用过,以后用到在写
<div id="app">
<div @click="sayHellow">
{{myName}}
</div>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
content: '你好 明天',
myName: 'red',
},
methods: {
sayHellow:function(){
console.log('hellow');
}
}
})
</script>
组件
基础
一个组件的 data
选项必须是一个函数!!!,组件必须在根实例得范围内否则是无效的
<body>
<!-- 无效的 -->
<child></child>
<div id="app">
<child></child>
</div>
<script>
Vue.component('child', {
data: function () {
return {
content: 'heheda'
}
},
template: '<div>{{content}}</div>',
})
var app = new Vue({
el: "#app",
})
</script>
</body>
局部注册 写法类似 只不过组件名 在根实例中写,
<script>
var child = {
data: function () {
return {
content: 'heheda'
}
},
template: '<div>{{content}}</div>',
}
var app = new Vue({
el: "#app",
components:{
'child':child
}
})
</script>
有时候我们在写li option td 这样的组件 放到ul select table 这样的标签里会出现组件标签上移或者select不显示的情况
这时候使用 is 来解决这种情况
<div id="app">
<select>
<child></child>
<option is="child"></option>
</select>
</div>
ref的使用 : 有时候 我们可能会需要获取 dom元素或者子组件, 那么在 vue中 直接给标签添加 ref 属性 就可以获取 dom ,如果给组件使用那么就是获取这个组件对象
<div id="app">
<child ref="cd"></child>
<div ref="ppap" @click="testComponent">我是标签 点我一下就变了</div>
</div>
<script>
var child = {
data: function () {
return {
content: '我是一个小组件'
}
},
template: '<div>{{content}}</div>',
}
var app = new Vue({
el: "#app",
components: {
'child': child
},
methods: {
testComponent: function () {
console.log(this.$refs.cd);
this.$refs.cd.content='我是小组件 我被获取了 所以我改变了';
console.log(this.$refs.ppap);
}
}
})
</script>
prop:父组件通过prop往子组件传参, 子组件接收这个参数,并把她赋给一个其他的变量,而不是直接修改父组件的参数,因为我们不能保证父组件传过来的参数只有这一个组件用,可能别的组件也会用,会影响其他组件
<div id="app">
<child ref="cd" :content="vexation"></child>
</div>
<script>
var child = {
props:['content'],
data: function () {
return {
myContent: this.content,
}
},
template: '<div>{{myContent}}</div>',
}
var app = new Vue({
el: "#app",
components: {
'child': child
},
data:{
vexation:'大姐又来闲聊来了,您不上班吗????????'
}
})
</script>
子组件给父组件传值,用 $emit('触发的方法名','参数1',.......)方法
<div id="app">
<child ref="cd" :content="vexation" @watch-me="watchMeFather"></child>
</div>
<script>
var child = {
props:['content'],
data: function () {
return {
myContent: this.content,
}
},
template: '<div @click="giveFather">{{myContent}}</div>',
methods:{
giveFather:function () {
this.$emit('watch-me','大姐终于走了,世界安静了');
}
}
}
var app = new Vue({
el: "#app",
components: {
'child': child
},
data:{
vexation:'大姐又来闲聊来了,您不上班吗????????'
},
methods:{
watchMeFather:function(msg){
// console.log(msg)
alert(msg);
}
}
})
</script>
prop的大小写 应该是 小写的 如果单词较长 使用 - 连字符 xx-xx, 同时也可以限制传入的类型,并且对传入的参数进行校验.
props:{
//可以仅仅简单的判断下类型
// content:[String,Number],
content:{
type:[String,Number],
//是否必须
required:true,
default:'当required为false,如果没传值,可以给他一个默认值',
//校验器 如果返回false vue会发出警告
validator:function (value) {
return value.length>0;
}
}
},
给组件绑定原生事件, 正常情况下 我们给组件的标签 绑定事件如 @click='xxx' 这样是不行的 ,因为在组件上, 此事的click是一个自定义事件,不是一个click事件, 如果我们想调用原生事件 需要在 @click.native 加上 native 这么写就可以了
<div id="app">
<!-- 直接给组件 @click是调用不了原生方法的 需要加.vative -->
<child @click.navtive="originClick"></child>
</div>
slot插槽:
使用情况:
1.当我们使用模板的时候,模板中的一部分内容,需要自己来定义,
2.如果我使用父组件来传参,那么我们在template中必须得用 v-html得形式,而且必须得在加个父层,与我们预期的结构不符合
注意:
1.<slot>默认值<slot> 如果在插槽中可以有默认值, 前提你没传参数
2.<child> <p>xxx<p></child> 如果 你在template中没写 slot 那么 child标签中里面的内容是不会显示的
3.具名插槽: 组件中 可以写入多个<slot> 但是你需要给他指定 name 否则多个slot只会把child中的内容多次添加到dom
<div id="app">
<child>
<h1 slot="header">
脑袋
</h1>
<h1 slot="main">
身体
</h1>
<h1 slot="footer">
脚
</h1>
<h1>
我是滥竽充数的
</h1>
</child>
</div>
<script>
var child = {
data: function () {
return {
// myContent: this.content,
}
},
template: `<div>
你好大兄弟
<slot name="header">默认值</slot>
<slot name="main">默认值</slot>
<slot name="footer">默认值</slot>
</div>`,
}
var app = new Vue({
el: "#app",
components: {
'child': child
},
data: {
aaaa: 'hi',
}
})
</script>
作用域插槽
使用情况:
1.当我们使用这个组件的时候,想要循环template里面部分标签,但是标签内容不固定,就要使用了.
注意:
1.<slot v-for="item in myContent" :eve = item></slot> 把item绑定给eve
2.<h1 slot-scope="ppap">{{ppap.eve}}</h1> "ppap" 代表着 从子组件获取的数据都给了ppap 所以ppap.eve就可以使用数据了, 2.5以上就可以在组件的内部中的任何元素上 使用 slot-scope,而以前只能写在<template></template>标签上
<body>
<div id="app">
<child :content="fatherList">
<template slot-scope="ppap">
<h1>
{{ppap.eve}}
</h1>
</template>
</child>
</div>
<script>
var child = {
props: ['content'],
data: function () {
return {
myContent: this.content,
}
},
template: `<div>
<slot
v-for="item in myContent"
:eve = item
>
</slot>
</div>`,
}
var app = new Vue({
el: "#app",
components: {
'child': child
},
data: {
fatherList: [1, 2, 3, 4, 5, 6, 7, 8, 9],
}
})
</script>
</body>
动态组件
固定模式就是 <component :is="cccc"></component> 其中cccc存的名字是组件名
<div id="app">
<component :is="cccc"></component>
</div>
<script>
var child = {
props: ['content'],
data: function () {
return {
myContent: this.content,
}
},
template: `<div>
haha
</div>`,
}
var app = new Vue({
el: "#app",
components: {
'child': child
},
data: {
cccc: 'child',
}
})
</script>