基本指令
插值语法
Mustache 语法 {{ }}
v-on
v-on 监听指令, 语法糖为@
在调用方法时,
例如: @click = “itemClick( )”若函数没有形参,可以省去小括号
若函数有形参,不可以省略小括号。
若不写小括号,浏览器会自动创建一个对象 event
若写上小括号不传入实参,则会显示underfunded
修饰符: 阻止冒泡行为 stop:@click.stop
阻止跳转行为 prevent : @click.prevent
v-bind
v-bind 动态绑定指令:
语法糖为 :,在组件中动态绑定一个变量时,不能使用驼峰命名法,必须用 " - " 拆解开
动态绑定class 属性
//以字符串型
:class = "active"
//以对象语法
:class = "{类名1: true, 类名2: false}"
例如:
:class = "{'active':isActive , 'line': isLine}"
//以键值对的形式在对象中显示,并且以布尔值动态添加,类名和布尔值都要以变量的形式存在
//数组语法
:class = "[]"
例如:
//数组里写对象,属性
:class = "[{'active': isActive},'line']"
//数组里写属性
:class = "['active':, 'line']"
//数组里写三元表达式
:class = [isActive? 'active': 'line']
动态绑定style属性
//以对象语法
:style = "{属性1: 属性值1,属性2: 属性值2}"
//以键值对形式存在需要加引导,不然会被当做变量使用
v-if
当获得的值为 false时 ,删除此元素,此元素将不存在,适合依次切换使用
v-show
当获得的值为 false 时,隐藏此元素,相当于 display 属性,适合显示和隐藏频繁切换使用
v-for
v-for 遍历指令:
//遍历数组
v-for = "(item,index) in movies"
//遍历对象
v-for = "(item,index,id) in movies" :key = "id"
注意: 在遍历时,需要给标签动态添加 key 值,便于后期修改数据时提高效率和性能
原理: 由于vue 最大的特点为双向数据绑定,数据一旦发生变化,就在页面中重新渲染,无疑循环对数据的变化是非常庞大的
若不加 key 值,会造成数据不能复用,需要重新渲染所有的数据,大大降低效率和性能 若加上key 值,在数据发生变化的时候,页面只会重新渲染修改后的数据,没有修改的数据会被重新复用,大大提高效率
添加的key 值必须是唯一的,例如id 最好不要使用 index
组件化
组件的使用必须在 Vue 实例挂载的 div 之内
三大步:
创建组件构造器
<script>
const cpnC = Vue.extend({
template: ' //这里的template属性是html 模板的 意思
<div>
<h2>iiiiiii<h2>
<h3>sdfjsefi<h3>
</div>
'
})
</script>
注册组件
Vue.component('my-cpn',cpnC) //第一个参数是创建的标签名,第二个参数是创建组件构造器的方法名,这样的注册方式注册的是全局组件
使用组件
组件实例对象
<body>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</body>
简化
简化注册组件的方式:在 Vue 实例或其他组件构造器中添加 component 属性
<script>
const app = new Vue({
el:'#app',
components:{
cpn1:cpnC1, //cpn1是指标签名,cpnC1是指构造组件方法名
cpn2:cpnC2 //可以注册多个组件
}
})
</script>
组件的创建、注册可以在任意其他组件中,或者在 Vue 实例中
组件数据的存放 data
在data中存储该组件的数据时,格式必须是个函数,而且要求返回一个对象,数据存放在返回值的对象里。(为了在多次使用组件时不产生相互影响)
data(){
return { 数据存放处 }
}
组件通信
父子组件的数据传递相当于自上而下的水管,不能逆流。这是vue设计理念的单项数据流。
父传子
父组件传给子组件,子组件不要对其进行修改,而是需要找一个变量将父组件传递的数值给赋值过来
然后对变量进行操作
props 属性
//1.创建一个父组件 Parent.vue,在data中添加一个parentAge
<template>
<div class="my-parent">
<h3>我是父组件</h3>
<p>父组件的年龄是:{parentAge}}</p>
</div>
</template>
<script>
export default {
data() {
return {
parentAge: 50
};
}
};
</script>
<style>
.my-parent {
text-align: left;
text-indent: 1em;
width: 1000px;
height: 500px;
border: 1px solid #555;
}
</style>
//2.创建子组件,在data中添加一个childAge
<template>
<div class="my-child">
<h3>我是子组件</h3>
<p>子组件的年龄是:{{childAge}}</p>
</div>
</template>
<script>
export default {
data() {
return {
childAge: 27
};
}
};
</script>
<style>
.my-child {
margin: 20px;
width: 760px;
height: 200px;
border: 1px solid red;
}
</style>
3.把父子组件关联起来,并通过v-bind(即简写“:”)将父组件中的 parentAge 值,传递给子组件
v-on绑定的属性名称deliverParentAge与data中定义的parentAge名称可以不一样
属性deliverParentAge通过v-bind绑定的,也是子组件中通过props接收的,而parentAge是要传递给子组件的数值,它是一个值
<template>
<div class="my-parent">
<h3>我是父组件,我想告诉我的子组件,我的年龄值是:{{parentAge}}</h3>
<h3>我要通过v-bind(即简写":")语法糖绑定一个属性deliverParentAge,将父组件的值传递到子组件中</h3>
<!-- 下面就是我的子组件 -->
<my-child :deliverParentAge="parentAge"></my-child>
</div>
</template>
<script>
import MyChild from "./Child";
export default {
components: { MyChild },
data() {
return {
parentAge: 49
};
}
};
</script>
//4.子组件通过props属性,在子组件中接收父组件传过来的值
<template>
<div class="my-child">
<h5>我是子组件,我可以通过属性props来接收父组件传过来的年龄值是:{{deliverParentAge}}</h5>
</div>
</template>
<script>
export default {
data() {
return {
childAge: 27
};
},
props: {
deliverParentAge: Number
}
};
</script>
子传父
$emit
//5.现在来修改父组件的值(这个不是真的修改而是通过this.$emit提交一个事件,将子组件的行为告诉父组件)
<template>
<div class="my-child">
<h5>我是子组件,我可以通过属性props来接收父组件传过来的年龄值是:{{deliverParentAge}},这是一个数字类型</h5>
<h5>并且,我要告诉他,他今年生日已经过了,所以他的年龄应该<button @click="AddAge">加1</button></h5>
下面我要通过this.$emit方法提交一个事件addParentAge,告诉我的父组件,他的实际年龄
</div>
</template>
<script>
export default {
data() {
return {
childAge: 27
};
},
props: {
deliverParentAge: Number
},
// 新建一个计算属性,将父组件原来的值加1
computed: {
parentActualAge() {
return this.deliverParentAge + 1;
}
},
methods: {
AddAge() {
this.$emit("addParentAge", this.parentActualAge);
}
}
};
</script>
//6.父组件通过语法糖v-on(即简写为“@”)来监听子组件提交的事件**addParentAge**
this.$emit提交的事件名称addParentAge,与方法handleAddParentAge名称可以不一样
addParentAge是子组件提交的事件名称,也是父组件通过v-on监听的事件名称,而handleAddParentAge是父组件自定义的方法名称
<template>
<div class="my-parent">
<h3>我是父组件,我想告诉我的子组件,我的年龄值是:{{parentAge}}</h3>
<h3>我要通过v-bind(即简写":")语法糖绑定一个属性parentAge,告诉子组件我的年龄值是:{{parentAge}}</h3>
<!-- 下面就是我的子组件 -->
<my-child :deliverParentAge="parentAge"
@addParentAge="handleAddParentAge"></my-child>
<h3>通过监听子组件提交的事件addParentAge,我知道到了自己的实际年龄应该是:{{parentAge+1}},并通过方法handleAddParentAge,在控制台打印出我的真实年龄</h3>
</div>
</template>
<script>
import MyChild from "./Child";
export default {
components: { MyChild },
data() {
return {
parentAge: 49
};
},
methods: {
handleAddParentAge(actualAge) {
console.log("父组件的实际年龄是:", actualAge);
}
}
};
</script>
生命周期钩子
目前了解的 vue2 生命周期钩子函数,分别有beforeCreate、created、beforeMount(组件挂载)、mounted、beforeUpdate(当这个钩子被调用时,组件 DOM 已经更新)、updated、activated(被 keep-alive 缓存的组件激活时调用,该钩子在服务器端渲染期间不被调用。)、deactivated
这些生命周期函数在页面加载,组件创建,渲染等各个时刻自己会被调用
[图片上传中...(image.png-a36993-1631772823585-0)]
[图片上传失败...(image-64da86-1631773136921)]
每个组件在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
路由Router
使用路由的步骤
第一步:创建路由组件
第二部:配置路由映射:组件和路径映射之间的关系
第三步:使用路由:通过 <router-link> 和 <router-view>
装路由
npm install vue-router --save
跑项目:
npm run dev cli2
路由参数的传递
-
可以手写完整的path
this.$router.push({path:'/user/${userId}'})
-
可以用parmas传递
this.$router.push({name:'user',parmas:{ userId: 123}})
-
也可以用query传递
this.$router.push({path:'register',query: { plan: 'private'}})
路由的懒加载
const Home = () => import('../views/home/Home.vue')
const Category = () => import('../views/category/Category.vue')
const Profile = () => import('../views/profile/Profile.vue')
const Cart = () => import('../views/cart/Cart.vue')
const Detail = () => import('../views/detail/Detail.vue')
默认路由的添加方式
routes:[
{
path: '',
redirect:'/home'
},
]
vuex状态管理
创建vuex项目
-
首先需要在某个地方存放代码
- 建文件夹 store ,在其中创建一个 index.js 文件
- 在index.js 文件中写入以下代码
<script> //index.js import Vuex from 'vuex' import Vue froms 'vue' Vue.use(Vuex)//使用vuex插件 const store = new Vuex.store({ //创建vuex对象 state:{ count :0 }, //vuex 的核心 mutations: { increment(state) { state.count++ }, decrement(state) { state.count-- }, actions: { }, getters: { }, modules: { } } }); //导出 vuex 对象,因为vuex实例要使用 export default store </script>
其次让所有的 Vue 组件都可以使用这个 store 对象
- 来到 mian.js 文件,导入 store 对象。并且放在 new Vue 中
- 这样,在其他 Vue 组件中,我们可以通过 this.$store 的方式,获取这个对象
在Vue实例中引入Vuex实例:
//main.js
import Vue from 'vue'
import App from './App'
import store from './store'
new Vue({
el:'#app',
store,
render :h => h(App)
})
在 App.vue 中
<template>
<div id = "app">
<p>{{count}}</p>
<button @click = "addition"></button>
<button @click = "decreament"></button>
</div>
</template>
<script>
export default {
name:'App',
component: {
},
computed:{
count: function(){
return this.$store.state.count
}
},
methods: {
addition(){
return.this.$store.commit('increament')
},
decreament: function(){
this.$store.commit('decreament')
}
}
}
</script>
总结:
- 提取一个公共 store 对象,用于保存在多个组件中共享的状态
- 将 store 对象放置在 new Vue 对象中,这样可以保证所有组件都可以用到
- 在其他组件中使用 store 对象中保存的状态即可
- 通过 this.$store.state 属性的方式来访问状态
- 通过 this.$store.commit ('muatation中方法')来修改状态
注意:
- 我们通过提交 mutation 的方式,而非直接改变 store.state.count
- 这是因为 Vuex 可以更明确的追踪状态的变化,所以不要直接改变 store.state.count的值
Vuex 的核心概念
- State 单一状态树 相当于组件中的 data 属性
- Getters 相当于组件中的 computer 属性
- Mutation 状态更新 相当于组件中的 methods属性
- Action 只有使用异步时才使用
- Module
axios网络请求
axios 在vue框架中用于向服务器请求数据,之前了解过一点jQuery 的AJAX 。vue框架的axios 基于Promise ,可以使用 Promise API
作品中用到的axios的请求方式,
axios.request( config )
另外有其他几种方式,用到再说
- axios.request(config)
- axios.get(url [,config])
- axios.post(url[data [,config]])
- axios.put(url [data [,config]])
- axios.delete(url [,config])
- axios.patch(url [data [,config]])
- axios.head(url [,config])
- axios(config)
默认的网络请求方法是get,如果需要发送多个请求,并发请求的话需要用到 all 方法。这里没有用到
import axios from 'axios'
export function request(config){
const instance = axios.create({ //创建axios实例的目的是为了方便使用全局配置,另一方面减少各个组件对axios框架的依赖性
baseURL: "http://xxxxxxx",
timeout:xxxx
})
//添加axios拦截器
instance.interceptors.request.use(config => { //添加请求拦截器,检测在请求网络数据时的状态
return config
},err=> {
console.log(err)
})
instance.interceptors.response.use(res => { //添加响应拦截器,页面在获取数据后进行检测状态
return res.data //成功则返回结果
},err => {
console.log(err);
})
return instance(config) //发送网络请求
}
这里 config 配置选项有必要了解
{
//服务器的地址,是必须的选项
url:'/user'
//请求的方式,默认是get
method:'get'
//如果url不是绝对地址,则会加上 baseURL
baseURL:'http://localhost:3000'
//headers是自定义要被发送的信息头
headers:{'X-Requested-with':'XMLHttpRequest'},
//params 是请求连接中的请求参数,必须是个纯对象
params: { ID:123 }
//timeout 定义请求的事件,单位是毫秒,如果请求事件超过设定时间,请求停止
timeout:1000
其他的用到再了解
}
创建完网络请求的axios实例 instance 后,各个组件需要请求各自的数据,这里不将所有组件请求的方法放在同一个页面中,将其分类
例如 home 首页
import { request } from './request'
export function getHomeMultidata(){
return request({
url:'/home/multidata'//将配置信息返回至request网络请求方法中请求数据
})
}//接下来在组件中引用该方法,获取存储和渲染数据
网友评论