Vue笔记目录
Vue 笔记
一、Vue的基本模板语法
1.1插值操作
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<h1>
我是vue新手我对你说{{ message }}
</h1>
<!-- Mustache不仅仅可以直接写变量,也可以写成表达式 -->
<h2>
我有{{ count * 2}}个苹果
</h2>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
message:'hello',
count:4
}
})
</script>
1.2插值操作中有关其他指令的使用
-
v-once 指令
语法:直接v-once 当给某个元素增加了这个指令后,该元素只会在最开始的时候显示对应的值,如果对其进行修改,则加入了这个指令的元素不会被修改。
-
v-html
语法:v-html=‘变量名’ 如果想要将一个元素解析成html格式在网页中呈现出来,就要在该元素上增加该指令。
-
v-text
语法:v-text=‘变量名’ 该指令会将标签内原有的数据进行覆盖,无法拼接
-
v-pre
语法:v-pre 该指令不会解析标签里边的内容,反而会将标签里边的内容原封不动的展示出来,
-
v-cloak
语法:v-cloak 该指令用于解析完js代码后才将渲染效果展示出来;在vue解析之前,div中有一个属性v-cloak;在vue解析之后,div中就没有属性v-cloak,给这个属性添加一个display:none;可以让用户看不见渲染过程。
1.3动态绑定的指令
-
v-bind
语法:v-bind:属性名 该指令用于动态绑定某个元素的属性,简写方式:直接在要绑定的属性名前加上: 。比如动态绑定a标签的href属性,动态绑定img的src属性。
-
v-bind动态绑定class类(对象语法)
语法:
<div id="app" v-bind:class="{要起的类名1:布尔值,要起的类名2:布尔值}">
这的布尔值,是要在Vue中,data属性事先定义好的。
-
v-bind数组语法
语法:
<h1 v-bind:class="['active','line']">{{message}}</h1>
-
v-bind动态绑定style
对象语法:
v-bind:style="{属性名:属性值,属性名:属性值}"
注:当属性值直接写值时,只需要加引号;如果要用data中的数据时,则值不需要加引号,但是data中的数值需要加引号
数组语法:
v-bind:style="[data中的属性名,data中的属性名]"
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <h1 :style="[baseStyle1,baseStyle2]">{{message}}</h1> </div> <script> const app = new Vue({ el:'#app', data:{ message:"你好啊", baseStyle1:{backgroundColor:"red"}, baseStyle2:{fontSize:"40px"} } })
-
1.4计算属性
在Vue中,data对象中含有一个computed属性,该属性为计算属性,使用该属性时,直接调用属性名(无需加括号,因为是一个计算属性)。
-
计算属性的复杂操作
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <h1>{{message}}{{totalPrice}}</h1> </div> <script> const app = new Vue({ el: '#app', data: { message: "总价格为:", books: [ { id: 1, name: '三国演义', price: 100 }, { id: 2, name: '西游记', price: 100 }, { id: 3, name: '水浒传', price: 100 }, { id: 4, name: '红楼梦', price: 100 } ] }, computed: { totalPrice:function(){ let sum=0 for(let i=0;i<this.books.length;i++){ sum+=this.books[i].price } return sum } } })
1.5事件监听
-
在Vue中使用v-on来完成事件的监听,语法:v-on:事件名称=“调用的函数”
<button v-on:click="add()">+</button> 简写语法: <button @click="add">+</button>
-
v-on的参数问题
当通过methods中定义方法,以提供@click调用时,需要注意参数问题:
1.如果该方法不需要提供额外的参数,那么方法后面的()可以不添加;
但是:如果方法本身有一个参数,你又给()省略的话,此时Vue会默认将浏览器生产的event事件作为参数传递到方法中
2.如果方法需要传入一个参数,同时也需要传递event事件,可以通过==$event==的方式来手动获取浏览器参数的event对象。
-
v-on修饰符
Vue提供了修饰符来进行处理一些事件:
- .stop 停止事件的冒泡
- .prevent 阻止浏览器的默认行为
- .keyCode 只当事件是从特定键触发时才触发的回调 语法:@事件名.按键名=“方法名”
- .native 监听组件根元素的原生事件
- .once 使某个事件只发生一次回调
1.6条件判断
-
v-if、v-else-if、v-else
Vue中的条件指令可以根据表达式的值在DOM中渲染或者销毁元素或组件
- v-if的原理:当v-if后面的条件为false时,对应的元素以及子元素不会被渲染;也就是根本不会有对应的标签被渲染
-
v-if与v-show的区别使用
v-if:当条件为false时,包含v-if指令的元素,根本就不会存在dom中
v-show:当条件为false时,v-show只是给元素添加了一个行内样式 dispaly:none
**使用场景:**当显示与隐藏很频繁时,使用v-show,当只有一次切换时使用v-if
1.7循环遍历
-
使用v-for来进行循环遍历,遍历数组
<!-- 只遍历元素 --> <ul> <li v-for="item in games" :key="item">{{item}}</li> </ul> <!-- 索引与元素一起拿到 --> <ul> <li v-for="(item,index) in games">{{index +" "+ item}}</li> </ul> </div>
-
使用v-for来遍历对象
<!-- 1.只获取value --> <ul> <li v-for="item in people" :key="item">{{item}}</li> </ul> <!-- 2.获取value和key --> <ul> <li v-for="(value,key) in people">{{value}}+{{key}}</li> </ul> <!-- 3.获取value和key和index --> <ul> <li v-for="(value,key,index) in people">{{value}}+{{key}}+{{index}}</li> </ul>
在v-for里边加上 ==:key=“item”==可以提高性能
-
数组中哪些方法是响应式(当数组内部数据改变,页面上的元素也会随之改变)
-
push() 往数组的末尾添加一个或者多个元素
-
pop() 删除数组中的最后一个元素
-
shift() 删除数组中的第一个元素
-
unshift() 在数组最前面添加一个或多个元素
-
splice() 作用:删除元素/插入元素/替换元素
- 删除元素:第一个参数代表起始位置,第二个参数代表要删除元素的个数(如果第二个参数不传,默认删除后面所有元素,包含起始值)
- 插入元素:第二个参数,传入0,后面跟上要插入的元素
- 替换元素:第二个参数,表示要替换几个元素,后面的元素用来替换前面的元素
-
sort() 对数组中元素进行排序
-
reverse() 对数组中的元素进行反转
-
Vue.set()方法 三个参数,(要修改的对象,索引值,修改后的值)
注意:通过索引修改数组中的元素不是响应式的
-
1.8表单绑定v-model(双向绑定)
-
语法:v-model=“data中的属性名”
-
实现原理
v-model的实现原理实际上进行了两个操作
1.v-bind绑定一个value属性
2.v-on 指令绑定给当前元素一个input事件
-
v-model与radio的结合使用
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <label for="man"> <input type="radio" name="man" value="男" v-model="sex">男 </label> <label for="woman"> <input type="radio" name="woman" value="女" v-model="sex">女 </label> <h1>您选择的性别是:{{sex}}</h1> </div> <script> const app = new Vue({ el: '#app', data: { message: '你好啊', sex:'' } }) </script>
-
v-model与checkbox的结合使用
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <!-- 单选按钮的演示 --> <label for="agree"> <input type="checkbox" name="agree" v-model="isAgree">同意 </label><br> <button :disabled="!isAgree">下一步</button> <br> <!-- 多选按钮演示 --> <input type="checkbox" value="鱼香肉丝" v-model="foods">鱼香肉丝 <input type="checkbox" value="过油肉" v-model="foods">过油肉 <input type="checkbox" value="红烧肉" v-model="foods">红烧肉 <input type="checkbox" value="酱猪蹄" v-model="foods">酱猪蹄 <h1>您要选择的食物是:{{foods}}</h1> </div> <script> const app = new Vue({ el:"#app", data:{ message:"你好啊", isAgree:false, //单选返回布尔值 foods:[] //多选返回数组 } }) </script>
-
v-model与select的结合使用
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <!-- 单选 --> <select name="fruit" v-model="fruit"> <option value="青瓜" >青瓜</option> <option value="苦瓜" >苦瓜</option> <option value="香瓜" >香瓜</option> <option value="甜瓜" >甜瓜</option> </select> <h1>您选择的水果是:{{fruit}}</h1> <br> <select name="foods" v-model="foods" multiple> <option value="鱼香肉丝">鱼香肉丝</option> <option value="葱爆肉">葱爆肉</option> <option value="过桥米线">过桥米线</option> <option value="红烧茄子">红烧茄子</option> </select> <h1>您选择的食物是:{{foods}}</h1> </div> <script> const app = new Vue({ el:'#app', data:{ fruit:'甜瓜', //单选返回字符串 foods:[] //多选返回数组 } }) </script>
-
v-model的修饰符
语法:v-model.修饰符名=“data中的属性名”
-
lazy修饰符
lazy修饰符可以让数据在市区焦点或者按回车时才会更新
-
number修饰符
number修饰符可以让输入框中的内容自动转换成数字类型
-
trim修饰符
trim修饰符可以过滤掉内容左右两边的空格
-
二、组件化开发
2.1注册组件的基本步骤
-
创建组件构造器,调用Vue.extend()方法,里边传入template代表的是要进行组件的 模板对象
该模板就是在使用到组件的地方,要显示HTML代码
-
注册组件,调用Vue.component()方法,里边有两个参数 (“要用的模板标签名”,组件构造器对象)
-
使用组件,在Vue实例的作用范围内使用组件
-
全局组件与局部组件
使用==Vue.component(“my-cpn”,cpnC)==这种方式注册的组件是全局组件,
在Vue的实例对象中component属性中注册的组件属于局部组件,局部组件只能在Vue的实例对象中使用,超出该Vue的实例对象外,浏览器不会对其进行解析。
基本使用:
<div id="app">
<!-- 3.使用组件 -->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpnC = Vue.extend({
template:`
<div>
<h1>我是标题</h1>
<p>我是第一个p标签的内容</p>
<p>我是第二个p标签的内容</p>
</div>`
})
// 2.注册组件
Vue.component("my-cpn",cpnC) //全局组件
const app = new Vue({
el: '#app',
data: {
},
//局部组件(只能在当前Vue的实例对象下使用)
/*
components:{
//cpn是使用时的标签名
cpn:cpnC
}*/
})
</script>
- 注册组件的语法糖格式
<div id="app">
<cpn></cpn>
<cpn2></cpn2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 1.创建组件构造器
// const cpnC = Vue.extend()
// 全局组件语法糖的创建方式
Vue.component('cpn', {
template: `
<div>
<h1>AAAA</h1>
<P>111111</P>
</div>
`
})
// 局部组件语法糖的创建方式
const app = new Vue({
el: '#app',
components: {
cpn2: {
template: `
<div>
<h1>BBBB</h1>
<P>2222</P>
</div>
`
}
}
})
</script>
2.2组件模板的分离写法
- 使用script标签,type类型为text/x-template,在该标签放模板,且给该标签设置一个id,与template中的id名对应
- 使用template标签,在该标签中放置模板,且给该标签设置一个id,与template中的id名对应
<div id="app">
<cpn></cpn>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 模板抽取的第一种写法 -->
<!-- <script type="text/x-template" id="cpn">
<div>
<h1>我是标题呀</h1>
<p>我是内容啊</p>
</div>
</script> -->
<!-- 模板抽取的第二种写法 -->
<template id="cpn">
<div>
<h1>我是第二个</h1>
<p>我是第二个内容</p>
</div>
</template>
<script>
// 1.注册一个全局组件
Vue.component('cpn',{
template:'#cpn'
})
const app = new Vue({
el:'#app'
})
</script>
2.3组件数据的保存
- 组件对象也有一个data属性(与Vue实例对象类似,也可以有methods等属性),但是这个data必须是一个函数,而且该函数返回一个对象,返回对象的内部存放着需要保存的数据。
<div id="app">
<cpn></cpn>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<template id="cpn">
<div>
<h1>我是第二个</h1>
<p>我是第二个内容</p>
<p>{{name}}</p>
</div>
</template>
<script>
// 1.注册一个全局组件
Vue.component('cpn', {
template: '#cpn',
data() {
return {
name: "我是数据,存储在返回对象中"
}
}
})
const app = new Vue({
el: '#app'
})
</script>
2.4父子组件的通信
- 通过props向子组件传递数据
- 通过 $emit 自定义事件向父组件发送消息
-
在组件中,使用props来声明需要从父级接收到的数据。
props的值有两种方式:
- 字符串数组,数组中的字符串就是传递时的名称
- 对象,对象可以设置传递时的类型,也可以设置默认值等,(在属性名的后面跟上要返回的类型)
<div id="app"> <!-- 传入变量要是用v-bind,如果不用将会直接将字符串赋给前面的属性值 --> <cpn v-bind:childfoods="foods" :childmessage="message"></cpn> </div> <!-- 在子组件中显示 --> <template id="cpn"> <div> <h1>{{childmessage}}</h1> <h1>{{childfoods}}</h2> <ul> <li v-for="item in childfoods">{{item}}</li> </ul> </div> </template> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> // 注册组件 const cpn = { template:'#cpn', // 父传子,使用props // 1.使用数组类型 // props:['childfoods','childmessage'] // 2.使用对象类型,可以完成类型限制 props:{ // 传入属性,可以设置其类型 // childfoods:Array, // childmessage:String // 提供一些默认值(默认值在没有传的情况下显示)default // require 当添加了require,值为true时,该变量必须传递 childmessage:{ type:String, default:'我是默认值类型', require:true }, childfoods:{ type:Array, // 类型是对象或者数组时,默认值必须是一个函数 // default(){ return {} } default:['我是默认数组1','我是默认数组2'], require:true } } } const app = new Vue({ el:'#app', data:{ message:"我是父组件中的元素", foods:['鱼香肉丝','蛋炒饭','尖椒肉丝'] }, components:{ cpn } }) </script>
-
组件通信-父传子(props中的驼峰命名标识)
组件通信,父传子的驼峰命名中,如果在子组件中定义的属性是以驼峰命名法定义的,那么在父组件当中就应该用 - 来代替每一个驼峰
<div id="app"> <cpn :child-message="message" :child-person="person"></cpn> </div> <template id="cpn"> <div> <h1>{{childMessage}}</h1> <h1>{{childPerson}}</h1> </div> </template> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> // 注册组件 const cpn = { template:'#cpn', props:{ childMessage:{ type:String, default:'' }, childPerson:{ type:Object, default(){ return {} } } } } const app = new Vue({ el:'#app', components:{ cpn }, data:{ message:'你好啊', person:{ name:'张三', age:18, hobby:['lol','吃鸡'] } } }) </script>
-
子传父(自定义事件)
当子组件需要向父组件传递数据时,就要用到自定义事件,用v-on也可以监听自定义事件。
自定义事件的流程:
- 在子组件中,通过 $emit() 来触发事件
- 在父组件中,通过v-on来监听子组件事件
<!-- 父组件模板 --> <div id="app"> <cpn @item-click="cpnClick"></cpn> </div> <!-- 子组件模板 --> <template id="cpn"> <div> <button v-for="item in categories" @click="btnClick(item)"> {{item.name}} </button> </div> </template> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> //子组件 const cpn = { template:'#cpn', data(){ return { categories:[ {id:1,name:'热门推荐'}, {id:2,name:'手机数码'}, {id:3,name:'家用家电'}, {id:4,name:'电脑办公'} ] } }, methods:{ btnClick(item){ // 发射事件 自定义事件 this.$emit("item-click",item) } } } // 父组件 const app = new Vue({ el:'#app', // 注册子组件 components:{ cpn }, methods:{ cpnClick(item){ console.log('cpnClick',item) } } }) </script>
个人总结:
父传子,需要在子组件中用props来声明出新的属性名来接收父组件中的内容;之后在父模板中使用v-bind将父组件中的内容赋给子组件,然后子组件模板直接展示自己内部的属性即可
子传父,需要在子组件中用 $emit()来发射一个自定义事件 给父组件;在子组件模板中直接展示自己内部的属性即可;之后在父组件模板中使用v-on来监听自定义事件,并将父组件中的内容赋值给该自定义事件
2.5父子组件的访问方式
-
父组件访问子组件:使用 c h i l d r e n = = 或 者 = = children== 或者== children==或者==refs
this.$children是一个数组类型,包含所有子组件对象
$refs是一个对象类型,默认是一个空对象;使用时在组件上给 ref赋值 例如:
<cpn ref="aaa"></cpn>
-
子组件访问父组件:使用 p a r e n t = = , 使 用 = = parent== ,使用 == parent==,使用==root 来访问组件的根组件
3.6插槽slot
组件的插槽:
组件的插槽可以使封装的组件更加具有扩展性,让使用者可以决定组件内部的一些内容到底展示什么。
-
基本使用方式:在组件模板中使用
<slot></slot>
标签来占据空位。如果在该标签内部填入相应的html代码,则会在网页中显示插槽的默认内容,如果不想显示默认内容,直接在组件写入其他元素,会将默认的样式全部覆盖。 -
具名插槽:给相应的插槽添加一个
name
属性,在要显示的元素标签内部添加一个slot
属性,想要替换哪个插槽,就将相应的name值赋值给slot。 -
编译作用域的概念
编译作用域指的是在哪一个组件模板下,寻找到的只能是当前组件作用域的属性,父组件不能够跨到子组件,子组件也不可能跨越到父组件。父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
作用域插槽的使用(在父组件中拿子组件的数据)
-
一句话总结:父组件替换插槽的标签,但是内容由子组件来提供。父组件对子组件所展示的内容不满意,想要换一种展示方式,就用作用域插槽。(内容在子组件,希望父组件来告诉我们,使用slot作用域插槽就可以了)
-
使用方式:
在子组件中的slot中这样写
<slot :data="languages"></slot>
,然后在父组件中的<cpn></cpn>
中,写上template这样写
<template slot-scope="slot"></template>
,在template内部写上要呈现出的效果内容。<div id="app"> <cpn></cpn> <cpn> <!-- 目的是为了获取子组件中的languages --> <template slot-scope="slot"> <span>{{slot.data.join(' - ')}}</span> </template> </cpn> <cpn> <!-- 目的是为了获取子组件中的languages --> <!-- VUE2.5之后支持的不仅仅是template --> <div slot-scope="slot"> <span>{{slot.data.join(' ~ ')}}</span> </div> </cpn> </div> <template id="cpn"> <div> <slot :data="languages"> <ul> <li v-for="item in languages">{{item}}</li> </ul> </slot> </div> </template> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> const app = new Vue({ el: "#app", // 注册子组件 components: { cpn: { template: '#cpn', data() { return { languages: ['java', 'c', 'c++', 'js', 'php'] } } } } }) </script>
三、Vue-CLI
Vue Cli 可以快速搭建Vue开发环境以及对应的webpack配置。
安装的脚手架3,但是想用2的版本,需要拉取2的模板
Vue CLI2初始化项目
vue init webpack my-project
my-project 是要设置的项目的名称
Vue CLI3初始化项目
vue create my-project
Runtime-Compiler和Runtime-only的区别
如果开发使用template,就需要选择Runtime-Comoiler;如果使用.vue文件夹开发,那就选择Runtime-only
- Vue-CLI2目录解析
Vue CLI3与2的区别
- vue-cli3移除的配置文件是根目录下的build和config等目录
- vue-cli3提供了vue ui命令
- 移除了static文件夹,新增了public文件夹,并且index.html移动到了public中
cli3的目录详解
三、Vue-router
3.1 Vue-router的基础
vue-router是Vue.js官方的路有插件,适合用于构建单页面应用,他是基于路由和组件的;
路由用于设定访问路径,将路径和组件映射起来;在vue-router的单页面应用中,页面的路径的改变就是组件的切换。
-
安装vue-router
npm install vue-router --save
-
在模块化中使用
- 1.导入路由对象,调用Vue.use()
- 2.创建路由实例,并且传入路由映射配置
- 3.在Vue实例中挂载创建的路由实例
-
Vue-router的使用步骤
-
创建路由组件
-
配置路由映射,组件和路径映射关系
-
使用路由,通过
<router-link>
和<router-view>
来显示组件内容。<router-link>
该标签是一个vue-router中已经内置的组件。他会被渲染成一个a标签,其中<router-link>
中有一个to属性,后面跟着路径地址,<router-view>
,该标签会根据当前的路径,动态渲染出不同的组件,<router-view>
是用来显示在<router-link>
里边内容位置的上方还是下方。在路由切换时,切换的是<router-view>
挂载的组件,其他内容不会发生改变。
-
<router-link>
的属性- to,用于跳转到指定的路径
- tag,可以指定
<router-link>
被渲染成什么组件,例如渲染成button,<router-link to="/home" tag="button">首页</router-link>
- replace,该属性不会留下history的记录,指定了replace,后退键不能返回到上一个页面中
- active-class,当
<router-link>
对应的路由匹配成功时,会自动给当前元素设置一个 router-link-active的class,设置active-class可以修改默认的类的名称。- 在进行高亮显示的导航菜单或者底部tabbar时,会用到该类
- 但是通常不会修改类的属性名,会直接使用默认的router-link-active即可;如果要对元素进行统一修改,需要在路由内部配置一个linkActiveClass属性,值为要修改的名称。
3.2路由懒加载
路由懒加载的作用主要就是将路由对应的组件打包成一个个js代码块,只有当某个路由被访问的时候,才加载它。
路由懒加载的方式:
这里使用Vue组件和Webpack的代码分割写法
const Home = ()=> import('../components/home.vue')
3.3 keep-alive与vue-router
-
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
两个属性:示例,
include='User,Profile'
- include 字符串或正则表达,只有匹配的组件会被保存
- exclude 字符串或正则表达式,任何匹配的组件都不会被缓存
-
router-view也是一个组件,如果直接被包在keep-alive里面,所有的路径匹配到的视图组件都会被缓存。
只有在用keep-alive时,才能使用activated、deactivated这两个函数。