前言
vue学习
提示:以下是本篇文章正文内容,下面案例可供参考
一、过滤器(filter)
filter:过滤器的作用就是对我们输入的内容做一次处理之后再展示,接受的数据为管道符号前面的值(包括全局过滤器和局部过滤)
<div id="app">
<input type="text" placeholder="请输入价格" v-model="price" />
<p>{{price|formatePrice|format}}</p>
</div>
<script>
// 全局过滤器
Vue.filter('format',(v)=>{
return v+'$'
})
new Vue({
el: '#app',
data: {
price: '',
},
filters: {
formatePrice(v) {
return '$' + v
},
},
})
二、监听(watch)
watch:watch监听某一个数据的改变,数据改变之后引起一些其他的操作
<div id="app">
<input type="text" placeholder="请输入年龄" v-model="msg" />
</div>
<script>
new Vue({
el: '#app',
data: {
msg: '',
},
watch: {
msg(v) {
if (v.indexOf('sb') !== -1) {
alert('你输入了不合适的内容')
}
},
},
})
</script>
//深度监听--
new Vue({
el: '#app',
data: {
userObj: {
username: 'chen',
age: 18,
},
},
watch: {
userObj: {
deep: true,
handler(v) {
console.log('您修改了值')
},
},
},
})
三、计算属性(computed)
计算属性:当依赖的值发生变化,重新计算结果 计算属性有缓存效果,当依赖的值没有发生变化,不会重新计算
<div id="app">
<input type="text" v-model="keyName" />
<ul>
<li v-for="(item) in filterList" :key="item.id">{{item.name}}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
keyName: '',
list: [
{ id: 1, name: '喜羊羊' },
{ id: 2, name: '美羊羊' },
{ id: 3, name: '懒羊羊' },
{ id: 4, name: '沸羊羊' },
],
},
computed: {
filterList() {
return this.list.filter(
(item) => item.name.indexOf(this.keyName) !== -1
)
},
},
})
</script>
计算属性中set和get
- get():1.当需要读取当前属性值时调用(初始化)/当依赖项变化时也调用该回调函数 2.根据相关数据计算并返回当前属性值
- set():监视:1.当属性值变化时调用该回调函数 2.根据最新的属性值计算相关数据
const vm = new Vue ({
data: {
firstName; ‘A’,
lastName: 'B'
},
computed: {
fullName: {
get () {
return firstName + ' ' + lastName;
},
set (value) { //fullName是要监听的属性,value是fullName的最新属性值
this.firstName = value.split(' ').[0];
this.lastName = value.split(' ').[1];
}
}
}
})
四、路由
- 路由分为hash模式和history模式
- hash模式就是url中有#;好用但是不好看
- history模式没有#,在发布之后需要在web服务器上做特殊配置;好看但是不好用
- vue路由默认是hash模式的
1.路由的基本使用
//npm install vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import home from '../pages/home.vue'
const router = new VueRouter({
routes: [
{
path: '/', //表示url中访问的地址
component: home, //表示对应的组件
name: 'Home', //名字
},
{
path: '/cart',
// 路由懒加载,
// 第一次页面初始化的时候不会加载这个js文件,
//当页面跳转到当前页的时候会请求这个文件。建议只用这种方式
component: () => import('../pages/cart.vue'),
name: 'Cart',
},
{
path: '/list',
component: () => import('../pages/list.vue'),
name: 'List',
},
{
path: '/user',
component: () => import('../pages/user.vue'),
name: 'User',
},
//当路径路由不正确,配置展示404页面
{
path: "*", // 匹配所有的
component: () => import("../views/PageNotFound"),
},
],
})
export default router
2.在vue路由中使用的标签
(1)router-link
router-link:最终被渲染成a标签
//通过路由跳转
<router-link to="/">【首页】</router-link>
<router-link to="/products">【列表】</router-link>
//通过name跳转--推荐使用
<router-link :to="{name:'List'}">
<i class="iconfont icon-bianji"></i>
<span>详情页</span>
</router-link>
(2)router-view
router-view:所有路由对应的组件都会被渲染到这个节点
<router-view></router-view>
3.路由跳转方式
(1)声明式路由跳转–router-link
1. 不带参数
<router-link :to="{name:'home'}">
<router-link :to="{path:'/home'}"> //name,path都行, 建议用name
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
2.带参数
<router-link :to="{name:'home', params: {id:1}}">
// params传参数 (类似post)
// 路由配置 path: "/home/:id" 或者 path: "/home:id"
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
<router-link :to="{name:'home', query: {id:1}}">
(2)编程式路由跳转–>this.$router.push()
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
1. 不带参数
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
2. query传参
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
// html 取参 $route.query.id
// script 取参 this.$route.query.id
3. params传参
this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
4. query和params区别
query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传, 密码之类还是用params刷新页面id还在
params类似 post, 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失
(3)query和params传参的区别
- query 传参配置的是path,而params传参配置的是name,在params中配置path无效
- query在路由配置不需要设置参数,而params必须设置
- query传递的参数会显示在地址栏中
- params传参刷新会无效,但是query会保存传递过来的值,刷新不变
(4)其他编程式路由跳转方法的区别
- this.$router.replace()
- this.$router.go(n)
this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
ps : 区别
this.$router.push
跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面
this.$router.replace
跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)
this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
(5)通过this.$route可以获取传递的参数
4.路由嵌套
(1)路由嵌套
{
path: '/user',
component: () => import('../views/user/index.vue'),
name: 'User',
children: [
{
path: 'orders',
component: () => import('../views/user/orders.vue'),
name: 'Orders',
},
{
path: 'info',
component: () => import('../views/user/info.vue'),
name: 'Info',
},
{
path: 'score',
component: () => import('../views/user/score.vue'),
name: 'Score',
},
],
},
(2)命名视图
同时展示多个视图,非嵌套展示
//路由配置
{
path: '/many',
name: 'Many',
component: () => import('../views/many.vue'),
// 一个页面显示多个路由,可以使用属性components
children: [
{
path: '',
components: {
test1: () => import('../views/many/test1.vue'),
test2: () => import('../views/many/test2.vue'),
test3: () => import('../views/many/test3.vue'),
},
},
],
},
<-! 页面展示->
<div>
<h2>这里添加多页面(many)</h2>
<router-view name="test1"></router-view>
<router-view name="test2"></router-view>
<router-view name="test3"></router-view>
</div>
5.路由导航守卫
(1)全局前置守卫
- 所有的页面跳转之前执行
- 回调函数中有三个参数
- to 到哪里去
- from 从哪里来
- next 是一个方法,需要调用。如果不调用,页面就不会执行
- beforeEach表示路由的前置守卫,路由跳转之前执行
router.beforeEach((to, form, next) => {
//判断当前页面是否需要登录--在路由中加meta:{needLogin:true}
if (to.meta.needlogin) {
//判断用户是否登录
if (localStorage.getItem('token')) {
next()
} else {
next({ name: 'User' })
}
}
next()
})
(1)全局后置钩子
router.afterEach((to, from) => {
console.log('路由跳转之后执行')
})
五、vueX学习
定义:VueX 是一个专门为 Vue.js 应用设计的状态管理架构,统一管理和维护各个vue组件的可变化状态
可以通过import { mapState, mapMutations, mapActions } from "vuex"获取;
1.State
vuex的基本数据,用来存储变量
state: {
count: 1,
cart: [
{ id: 1, name: 'chen1' },
{ id: 2, name: 'chen2' },
{ id: 3, name: 'chen3' },
],
},
- 通过$store.state.count获取
- 通过 …mapState([“count”])映射到计算属性(computed)获取
2.Getters
从基本数据(state)派生的数据,相当于store的计算属性
// 相当于计算属性
getters: {
cartLength(state) {
return state.cart.length
},
},
- store.getters.cartLength
//在组件中,则要写在计算属性中,
computed: {
doneTodos () {
return this.$store.getters.cartLength;
}
} - …mapGetters([‘cartLength’])获取
3.Mutations
提交更新数据的方法,必须是同步的(如果需要异步使用action)
mutations: {
addCount(state, payload) {
state.count += payload.step
},
reduceCount(state, payload) {
state.count -= payload.step
},
// 接口
getDataEnd(state, payload) {
console.log(payload)
},
},
- <button @click=“addCount({step:2})”>增加
…mapMutations([‘addCount’]), - reduce () {
this.$store.commit(‘reduceCount’, { step: 2 })
}
4.Actions
和mutation的功能大致相同,不同之处在于:
- Action 提交的是 mutation,而不是直接变更状态;
- Action 可以包含任意异步操作。
- 不推荐在此处修改数据,在此处修改的数据不能被vue-devtools工具记录
// 此处添加异步请求
actions: {
addAsync(context, payload) {
console.log(context);
console.log(payload);
// 不建议在action中改变数据
// context.state.count += payload.step;
setTimeout(() => {
context.commit("add", payload);
}, 3000);
},
async getData({ commit }) {
try {
let result = await axios.get('http://localhost:1337/api/v1/products')
commit('getDataEnd', result)
} catch (error) {
console.log(error)
}
},
},
- …mapActions([‘getData’])
- this.$store.dispatch(“addAsync”, {
step: 3,
});
5.Modules
模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,管理更为方便
六、引入图片问题
1.引入图片路径问题
如果图片路径参数写在js代码中,图片需要通过require进行引入,require会自动调用webpack的文件解析功能
import img from "./assets/logo.png";
data() {
return {
img: img, //require("./assets/logo.png"),
};
},
七、组件化开发
1.定义局部组件
可以使用一下两种方式定义局部组件 ,局部组件需要先注册在使用
- 在html结构中定义template模版
- 在script结构中使用模板字符串
<body>
<div id="app">
<selfcom></selfcom>
<con></con>
</div>
<template id="define">
<h2>添加一个自定义组件模版</h2>
</template>
<script>
// 自定义组件命名规则---不能出现大些字母--需要先注册在使用
const selfcom = {
template: `<div>妈呀</div>`,
}
const con = {
template: '#define',
}
new Vue({
el: '#app',
data: {},
components: {
selfcom,
con,
},
})
</script>
</body>
2.定义全局组件
全局组件不需要注册,可以直接使用可以在全局组件中添加conponents注册局部组件在全局组件中使用
<div id="app">
<con></con>
</div>
<script>
// 自定义组件
const self = {
template: '<em>这里是自定义组件的内容</em>',
}
Vue.component('con', {
template: '<div>添加全局组件<self></self></div>',
components: {
self,
},
})
3.创建动态组件
使用组件<component :is=“current”><component>
<div id="app">
<button @click="current='index'">首页</button>
<button @click="current='info'">详情</button>
<button @click="current='user'">我的</button>
<component :is="current"></component>
</div>
<script>
const index = {
template: '<h1>这是首页<h1>',
}
const info = {
template: '<h1>这是详情<h1>',
}
const user = {
template: '<h1>这是我的<h1>',
}
new Vue({
el: '#app',
data: {
current: 'index',
},
components: {
index,
info,
user,
},
})
4.组件传参问题
(1)父传子
在父组件中可以通过v-bind绑定属性,传递给子组件,可以传递的数据包括数字,对象,数组等
//接收父组件传值
props['data']
//可以自定义接收过来的数据类型,对传递的数据进行默认的配置
props: {
data: {
type: Object,
default: '默认值',
required: true,
},
},
(2)子传父
父子组件的关系可以总结为prop向下传递,事件向上传递。父组件通过prop给子组件下发数据,子组件通过事件给父组件发送信息。
//在子组件中通过事件派发
this.$emit('change-num', this.count)
//传递的父组件中通过事件监听 触发回调函数
this.$on('change-num',this.numHandel())
numhandle(v){
//此时v为子组件中派发的数据
}
(3)非相关组件传参(事件总线)
创建一个空白的vue实例,只用来做事件派发和监听,实现数据的通信和传递
const busEvent=new Vue()
//事件派发
busEvent.$emit('changEvent',this.num)
//事件监听
busEvent.$on('changeEvent',this.changeHandle())
//此时触发回调函数 changeHandle()
//在创建的项目的main.js配置事件总线
const busEvent=new Vue()
Vue.prototype.$busEvent=busEvent
//在其他组件中可以通过this使用该事件总线
this.$busEvent.$emit()
this.$busEvent.$on()
5.keep-alive
保证组件不被销毁,该页面不再被重新渲染 ,在<keep-alive><keep-alive>组件上可以添加两个属性include 表示包含, exclude 表示不包含,逗号分隔字符串