vue
vue指令
vue的创建
let vm = new Vue({
//挂载点
el: '#app',
data: {
isShow: true
},
// 方法
methods: {
toggleLoading() {
this.isShow = !this.isShow;
}
}
})
模板的指令
v-html v-text v-bind
<p v-html="msg"></p>
<p v-html="'hello'"></p>
<p v-html="'hello' + 1"></p>
<p>{{'hello' + 1}}</p>
<p v-bind:class="activeIndex === index?'active':''">234</p>
<p :class="activeIndex === index?'active':''">234</p>
data: {
msg: 'hello'
}
条件渲染的指令
v-if和v-else 配合使用条件为真则显示v-if的内容为假显示v-else
<p v-if="">1111<p>
<p v-else>1111<p>
v-show 和v-if 相同判断显示和隐藏的
<p v-show="">1111<p>
v-if和v-show的区别 :v-if条件为真 则渲染dom 为假则渲染,v-show条件为真 则显示dom 为假则隐藏dom。
for循环指令
v-for 遍历数组对象
<ul>
<li v-for="(item,index) in arr" @click="del(index)">
<p>{{index}}</p>
</li>
</ul>
key值
vue有就地复用的策略,所以切换为手机时,文本框还是原来的dom,会保留原来的值 解决方案: 加key值
<p v-if="isShow">用户名<input type="text" class="user" key="a"></p>
<p v-else>电话<input type="text" class="tel" key="b"></p>
数组和对象的更新检测
由于 JavaScript 的限制,Vue 不能检测以下数组的变动:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
当你利用索引直接设置一个数组项时,例如:this.arr[0] = newValue 不会触发视图更新
当你添加对象属性,例如:this.obj.naem = lili 不会触发视图更新
为了解决第一类问题,以下两种方式都可以实现和this.arr[0] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:
// Vue.set
Vue.set(this.arr, index , 新值)
Vue.set(this.obj, key , 新值)
// vm.$set
vm.$set(vm.arr,index , 新值)
vm.$set(vm.arr,key , 新值)
v-model
- v-model可以进行双向数据绑定, 表单元素值改变,则数据改变。 同样,如果数据改变,表单元素值也一起改变。
- 只能加给表单元素
<input type="text" class="user" v-model="msg">
data: {
msg: ''
}
v-on : 事件绑定和绑定修饰符
事件绑定:
<p v-on:click="fun"></p> //不传参
<p v-on:click="fun"></p> //不传参可以接收e事件对象
<p @click="fun(1)"></p> //传参
<p @click="fun(1,$event)"></p> //传参接收e事件对象
methods:{
fun(){ }
fun(e){ }
fun(num){ }
fun(num,e){ }
}
事件绑定修饰符:
<p @click.stop="fun"></p> //阻止冒泡
<p @click.prevent="fun"></p> //事件默认事件
<p @keyup.enter="fun(1)"></p>
v-once
v-once:只渲染一次 数据改变也不会在更新
<p v-once>{{msg}}</p>
data;{
msg:...
}
methods , computed , watch
methods
methods属性:里面的方法会在数据发生变化的时候,只要引用里面的方法,方法就回自动执行,又是有多个地方调用了一个方法那么这个方法被调用几次就回执行几次。
computed
computed属性(计算属性)
- 观察者:计算属性只执行一次
- 计算属性必须是有返回值才能用
- 只有依赖的变量发生变化是 计算属性才会再次执行 否则总是从缓存中取处上一次的值。
计算属性该属性里面的方法必须要有return返回值,这个返回值就是(value值)。有几个关键点
- 计算后属性不需要在data中重复定义
- 计算后属性必须渲染后,绑定的方法才会生效这里指就是定义后的变量名在上面html中显示
- 计算后属性绑定的方法中的任意变量值更新,方法都会被调用比如说方法中一个变量A,变量A变了函数会重新调用
- 计算后属性为只读属性(不可写)计算后属性为只读属性
methods和computed计算属性的区别的区别
- 如果一段业务流程没有返回值,不能使用computed,可以用methods完成
- 如果有返回值,但是业务代码没有依赖响应式数据,也不能用computed
- 除此之外,computed要优先使用。
- computed在计算一次之后,会缓存结果,下次使用时,会从缓存中直接获取结果。它所依赖的响应式数据发生变化,它才会再次计算。
- 而methods方法,在视图编译时,调用几次,就会执行几次。
watch
watch :是监听属性, 这个监听的是data属性里面的数据 当监听的数据发生了改变 就回执行监听的代码
- 监听响应式数据的变化(初始化时并没有执行),数据变化,则执行对应的业务代码
- 如果在初始化时希望执行一次,则添加immediate
data: {
price: 200,
num: 12,
msg: 'hello',
total: 0
},
1.
watch: {
// 监听响应式数据price的变化,一旦发生变化,则执行监听的代码
price(){
console.log('计算price一次')
this.total = this.price * this.num
},
num(){
console.log('计算num一次')
this.total = this.price * this.num
}
}
2.
watch: {
// 监听响应式数据price的变化,一旦发生变化,则执行监听的代码
price:{
handler(){
console.log('计算price一次')
this.total = this.price * this.num
},
// 实例初始化时自动执行
immediate: true
},
num(){
console.log('计算num一次')
this.total = this.price * this.num
}
}
生命周期函数
生命周期函数 (钩子函数) : 在实例化的某个时间点会自动触发的函数
- beforeCreat: 注入数据之前自动执行,此时不能访问到data数据
- created: 当数据已经注入,但模板还没有编译渲染时自动执行的函数 在实例化的过程中,只会自动执行一次,此时能访问到data数据
- beforeMount: 挂载之前,此时访问到的DOM还没有填充数据
- mounted: 挂载完成之后,此时访问的DOM已经填充完数据了
- beforeUpdata: 更新数据之前,此时访问到的DOM还没有更新数据
- update: 更新数据之后出发,此时访问的DOM已经是更新之后的数据了
- beforeDestroy: 销毁实例之前,此时可以访问到data数据,还没有销毁实例 , 没有相应效果,改变data数据不会出发试图的更新了
- destroy: 销毁实例之后,此时可以访问到data数据,已经销毁实例,没有相应效果,改变data数据不会出发试图的更新了
beforeDstory和destory的官方说法: beforeDstory:实例销毁之前调用。在这一步,实例仍然完全可用。 destory:实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
//数据注入之前,此时访问不到data中的数据
beforeCreate() {
console.log(' beforeCreate----' + this.msg)
},
//数据注入之后,此时可以访问data中的数据
created() {
console.log('created----' + this.msg)
},
//挂载之前,此时访问到的DOM还没有填充数据
beforeMount() {
console.log('beforeMount---')
console.log(this.$el)
},
//挂载完成之后,此时访问到的DOM已经填充数据
mounted() {
console.log('mounted----')
console.log(this.$el)
},
//在更新之前,此时访问到的DOM还没有更新为新的数据
beforeUpdate() {
console.log('beforeUpdate----')
console.log(this.$el.innerHTML)
},
//更新之后,此时访问到的DOM已经更新为新的数据
updated() {
console.log('updated----')
console.log(this.$el.innerHTML)
},
//销毁之前,此时data数据可以访问到
beforeDestroy() {
console.log('beforeDestroy----')
},
////销毁之前,此时data数据也可以访问到,没有响应式效果。数据更新,不会再触发视图更新
destroyed() {
console.log('destroyed----')
}
class动态绑定
class动态绑定: v-bind:clsss="",或 :class="" class里可写变量字符串或对象数组
变量的写法 : 比如有一个变量 activeClss='active'
写法 :<p v-bind:class="activeClss"></p>
字符串写法
<p v-bind:class="'active'"></p>
绑定对象
<!-- 绑定对象 -->
<!-- active 这个 class 存在与否将取决于数据属性 isActive 的真假 -->
<!-- <p :class="{active:isActive}">11111</p> isActive真添加active为假不添加 -->
<!-- <p :class="{active:isActive,bg:isBg,'text-danger': true}" class="f60">11111</p> 可以绑定多个 -->
<!-- <p :class="classObj" class="f60">11111</p> 在computed属性里面 -->
computed: {
classObj() {
return {
active: this.isActive,
bg: this.isBg,
'text-danger': true
}
},
}
绑定数组
<!-- 绑定数组 -->
<!-- <p :class="['active','bg']">11111</p> -->
<!-- <p :class="[activeClass,bgClass]">11111</p> -->
<!-- <p :class="[isActive?activeClass:'',bgClass]">11111</p> 表达式的方式 -->
<!-- <p :class="[classObj2,classObj3]">11111</p> 在computed属性里面 -->
computed: {
classObj2(){
return [this.isActive?this.activeClass:'',this.bgClass]
},
classObj3(){
return ['f60']
}
}
表单输入绑定和修饰符
v-model : 输入宽 复选框 单选框 下拉框 都可以用这个
表单的修饰符
- v-model.lazy: 一边情况只要数据改变就会更新数据 加了.lazy是在失去输入的焦点时 ,在更新数据
- v-model.number : 接收的数据会自动转换为数值型
- v-model.trim : 会自动去掉数据前后空白
组件
通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 Vue.component 全局注册的:
组件的定义
组件的特点:
- 组件的配置和Vue实例基本一致
- 不同之处: (1)没有el,而是用template替代 (2)data不是对象,而是一个有返回值的函数
- 组件的名字定义时,首字母大写,驼峰命名,在模板中使用时,要改为小写,多个单词加'-'
- 子组件不能直接调用根组件的数据
- 模板只能有一个根元素
全局组件的定义
//定义一个名为 button-counter 的新组件
Vue.component("ButtonCounter",{
template:`<p>{{msg}}</p>`,
data(){
return { msg:"hello"}
}
methods:{}
})
局部组件的定义
//定义一个名为 button-counter 的新组件
let ButtonCounter = {
template:`<p>{{msg}}</p>`,
data(){
return { msg:"hello"}
}
methods:{}
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
// 注册子组件
components: {
ButtonCounter
}
})
组件的复用:
注册一个组件是可以复用的,可以根据自己的需求随意的复用 ,没复用一次组件相当与每次都创建一个实例复用的组件互相是不被干扰的
组件的传值
父组件像子组件传值:
- 父组件通过自定义属性将数据传递给子组件
- 子组件通过props属性接收父组件传递的值
父组件:
模板: <com :type='msg'></com>
数据: msg = 'book'
注册: components: {
com: com
}
子组件:
const com = {
props: [ 'type' ],
template:``,
data(){}
}
子组件像父组件传值:
- 子组件通过自定义事件 向父组件传值
父组件:
模板: `<com @del="delUser"></com>`
方法:
methods: {
delUser(数据){
}
}
子组件:
模板: `<button @click=”send”></button>`
方法:
methods: {
send(){
this.$emit('del',数据); //del是自定义事件
}
}
非父子组件传递数据
有时候两个组件也需要通信(非父子关系)。当然Vue2.0提供了Vuex,但在简单的场景下,可以使用一个空的Vue实例作为中央事件总线。
- 定义一个全局的空Vue实例作为中央事件的总线:比如:var Bus = new Vue();
- 像某个组件传递数据 使用 Bus.emit("自定义事件",要传递的数据),传递数据
- 接收传递够来的数据 的在created钩子函数里面使用 Bus.$on("传递数据的自定义事件",(数据)=>{}),接收数据
组件的细节
特殊标签中组件的使用
有些 HTML 元素,诸如 ul、ol、table 和 select,对于哪些元素可以出现在其内部是有严格 限制的。而有些元素,诸如 li、tr 和 option,只能出现在其它某些特定的元素内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。
解决方案: 只需修改模板 (用匹配的标签,添加is属性,指向相应的组件)
<div id="app">
<!-- 特殊标签中组件的使用 -->
<table>
<!-- 代码混乱 -->
<!-- <row></row>
<row></row>
<row></row> -->
<!-- 解决方案 -->
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</table>
<script>
// 行组件
const Row = {
template: `
<tr>11111</tr>
`
}
var vm = new Vue({
el: '#app',
data: {
},
methods: {},
components: {
Row
}
});
</script>
获取原声DOM
有时候我们的有些需求不是Vue能帮我们完成的, 我们需要原声DOM完成
列如:楼梯导航滚动加载等
- 在模板中给需要获取dom的标签添加 ref属性 参数自定义 列如:ref='header'
- 在vue的实例中用 let dom = this.$ref.header
<div id="app">
<div class="header" ref="header1">
</div>
<div class="floor" v-for="item in arr" ref="floor">0</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
arr: [1,2,3]
},
methods: {},
mounted(){
document.onclick = ()=>{
// this.$refs: 返回的是对象,键名即为ref属性定义的名称,值为对应的dom对象
console.log(this.$refs)
// console.log(this.$refs.header1)
// 如果是v-for遍历出来的ref属性名同为floor的dom,$refs.floor返回的是数组
}
}
});
</script>
props的定义方式
-
数组类型 :
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
-
对象类型
通常你希望每个 prop 都有指定的值类型。这时,你可以以对象形式列出 prop,这些属性的名称和值分别是 prop 各自的名称和类型:
这不仅为你的组件提供了文档,还会在它们遇到错误的类型时从浏览器的 JavaScript 控制台提示用户对象类型:
props: { 基本的类型检查 (null,匹配任何类型) title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object msg:[String,Number] 可以定义多个类型 必填 msg:{ type:String, required:true, } 带有默认直播 msg:{ type:String, default:"123" } 引用类型的默认值 对象或数组默认值必须从一个工厂函数获取 arr: { type: Array, default(){ return [1,2,3] } }, 自定义验证函数 当验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。 msg:{ validator:function(value){ 这个值必须匹配下列字符串中的一个 return ["a","b","c"].indexOf(value) !== -1 } } }
动态组件
如果你的需求是结构不改变 里面的数据改变 那么可以用一个组件改名里面的数据
模板:
<div id="app">
<ul>
<li @click="toggle('a')">a</li> 点击传递数据
<li @click="toggle('b')">b</li>
<li @click="toggle('c')">c</li>
</ul>
<tab-cont :type="type"></tab-cont> 通过自定义属性传递数据
</div>
子组件:
let TabCont = {
props:["type"], 接收传递过来的数据
template:`
<ul>
<li>内容{{type}}</li>
</ul>
`,
}
Vue实例(跟组件)
let vm = new Vue({
el:"#app",
data:{
type:"a",
comNmae:'TabCont'
},
methods: {
toggle(comNmae,type){
this.type = type
}
},
components:{
TabCont,
}
})
需要在点击不同标签时,动态切换下方组件,可以用动态组件解决
模板:
<div id="app">
<button @click="toggle('comA')">toggle</button>
<button @click="toggle('comB')">toggle</button>
<component :is="com"></component>
</div>
子组件:
let comA = {
template:`
<p>comA组件的内容</p>
`
}
let comB = {
template:`
<p>comB组件的内容</p>
`
}
Vue实例(跟组件)
let vm = new Vue({
el: '#app',
data:{
com: 'comA'
},
components:{
comA,
comB
},
methods:{
toggle(type){
this.com = type
}
}
});
keep-alive组件
keep-alive 是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
include:接受一个字符串或正则表达式作为参数,匹配的组件会被缓存
exclude: 接受一个字符串或正则表达式作为参数,匹配的组件不被缓存
使用include和exclude接收的的参数 是组件的配置中的name属性 const comB = { name:参数, template:``, }
用法:
<keep-alive include="keepingCom">
<!-- name为keepingCom的组件状态将被缓存 -->
<component></component>
</keep-alive>
<keep-alive include="comA,comB">
<!-- 缓存comA或comB,结合动态组件的is属性使用 -->
<component :is="current"></component>
</keep-alive>
<!-- 进行动态判断 -->
<keep-alive :include="keepingComs">
<router-view></router-view>
</keep-alive>