前端 -- Vue2快速入门

1、MVC、MVP与MVVM模式

MVC是应⽤最⼴泛的软件架构之⼀,⼀般MVC分为:
Model( 模型 )、Controller( 控制器 )、View( 视图 )。
这主要是基于分层的⽬的,让彼此的职责分开。View ⼀般通过 Controller 来和 Model 进⾏联系。Controller是 Model 和 View 的协调者,View和Model不直接联系,基本联系都是单向的。
在这里插入图片描述
1、View 传送指令到 Controller
2、Controller 完成业务逻辑后,要求 Model 改变状态
3、Model 将新的数据发送到 View,⽤户得到反馈

MVP 模式将 Controller 改名为 Presenter,同时改变了通信⽅向。
在这里插入图片描述
1、各部分之间的通信,都是双向的。
2、View 与 Model 不发⽣联系,都通过 Presenter 传递。
3、View ⾮常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,⽽ Presenter⾮常厚,所有逻辑都部署在那⾥。

MVVM
MVVM 是把 MVC 的 Controller 和 MVP 的 Presenter 改成了 ViewModel。View 的变化会⾃动更新到 ViewModel,ViewModel 的变化也会⾃动同步到 View上显示。这种⾃动同步是因为 ViewModel 中的属性实现了 Observer,当属性变更时都能触发对应的操作。
在这里插入图片描述
2、单文件组件的创建:template

<template>
    <div class="hello">
        <h1>第一个单文件组件</h1>
        <p>我的名字叫:{{myname}}</p>
    </div>
</template>
<script>
// 单文件组件的使命是被别人引入来使用
// 传统方式是使用module.exports来暴露成员
// 建议的方式是使用export default,这是用来暴露默认成员。因为一个vue文件只描述一个组件,所以这个组件就可以当成默认需要返回的对象
// export default所返回的对象就是当前vue文件所描述的组件对象,这个组件对象是包含着完整的结构功能和样式
// 我们所返回的对象本质是是编译完成之后的组件对象,里面当然包含着结构功能和样式
export default {
    data(){
        return {
            myname:'小明同学'
        }
    }
}
</script>


<style lang='less' scoped>
// lang:可以指定样式的类型,如指定预处理器less
// scoped:定义当前样式是组件作用域样式:只有在当前组件中可以使用
h1{
    color:red;
}

</style>

3、插值表达式、v-text 、v-html、v-bind、v-for、v-model、v-on、v-show 、v-if

   插值表达式 <p>{{msg}}</p>

v-text

1.v-text中可以写和插值一样的表达式
2.V-text会将标签之间的内容完全替换,而插值可以根据需要部分替换
<p v-text="msg">不要干掉我</p>

v-html

1.它可以解析html结构
2.它会完全的覆盖标签之间的原始的内容
<p v-html='msg'>aa</p>

v-bind

 链接: <a v-bind:href="'/del?id='+id">删除</a>   
 样式:<p v-bind:style='"font-size:"+fontsize'>我有自己的字体大小</p> 
 类:<p :class="{red:isred}">我是红色吗?</p>     

v-for

1.循环数组
<标签 v-for='(value,index) in arr' :key='index'></标签>
2.循环对象
<标签 v-for='(value,key,index) in obj' :key='key'></标签>
:key属性具有唯一性,不能重复,它能够唯一标识数组的每一项
    将来数据中的某一项的值发生了改变,则v-for只会更新当前项对应的这个dom元素的值,而不是更新整个数据,从而提高效率

v-model

实现双向绑定的
1.修改数据,页面内容动态变化
2.修改页面内容,数据也有相应的动态变化

用户名: <input type="text" v-model="username"> <br>
密码:<input type="password" v-model="password"> <br>

export default {
    data () {
        return {
            msg:'hello',
            username:'',
            password:''
            
        }
    }

v-on
作用就是用来对元素进行事件绑定的

<标签 v-on:事件类型='事件处理函数'></标签>
<标签 v-on:事件类型='事件处理函数(参数)'></标签>

简写语法 :<标签 @事件类型=‘事件处理函数’>

v-show和v-if
都能实现元素是否显示在页面中

<标签 v-show='bool值'>
<标签 v-if='bool值'>
如果bool值为True,则显示,否则看不到

v-show:是通过为元素设置display:none的样式来实现元素的显示和隐藏的,如果是隐藏则添加这个样式,否则不添加这个样式

v-if:是通过元素的创建和销毁来实现元素是否可见,如果为true,则创建这个元素,否则不创建。
v-if分支结构v-else-if

其他指令
v-pre:原样输出,不解析当前的指令

v-once:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能
v-cloak:这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕

4、ref和$refs
类似dom的元素选择方式:document.querySelector(‘input’)

// 为元素设置ref属性
编号:<input type="text" v-model="newbrand.id" ref="bid"/>
// 在mounted钩子函数中通过this.$refs获取元素,并设置聚焦
	mounted () {
    	console.log(this)
    // 获取元素,设置聚焦
    	this.$refs.bid.focus()
}

5、局部指令

创建

export default {
  directives: {
    // 指令名称:{配置定义}
    myfocus: {
      // 当被绑定的元素插入到 DOM 中时…当指令添加到元素,正准备进行解析渲染时
      // 参数:
      // 1.el:当前使用这个指令的元素
      inserted (el) {
        console.log(el)
        el.focus()
      }
    },
    // 设置颜色
    setcolor: {
      inserted (el, binding) {
        console.log(binding)
        el.style.color = binding.value || '#000'
      }
    }
  }
}

使用

<input type="text" v-model="newbrand.bname" ref='bname'  v-myfocus/>

6、全局指令
在utils创建mydirectives.js文件

export const myFocus = {
  inserted (el) {
    console.log('这是全局指令的功劳')
    el.focus()
  }
}

export const setcolor = {
  inserted (el, binding) {
    el.style.color = binding.value
  }
}

使用

import { myfocus, setcolor } from '../utils/mydirectives.js'
export default {
  // 注册指令
  directives: {
    myfocus: myfocus,
    setcolor
  }
}
<input type="text" v-model="newbrand.bname" ref='bname'  v-myfocus/>

在这里插入图片描述
7、过滤器

局部

export default {
  // 添加过滤器
  filters: {
    dateFormat: (data, spe) => {
      var year = data.getFullYear()
      var month = data.getMonth() + 1
      var day = data.getDate()
      return year + spe + month + spe + day
    }
  }
}

使用

<td>{{value.btime | dateFormat('/')}}</td>

全局

在utils创建myfilters.js文件

export const dateformat = (data, spe) => {
  spe = spe || '/'
  var year = data.getFullYear()
  var month = data.getMonth() + 1
  var day = data.getDate()
  return year + spe + month + spe + day
}

使用

import { dateformat } from '../utils/myfilters.js'
export default {

  // 注册过滤器
  filters: {
    dateformat
  }
}
 <td>{{value.btime | dateformat}}</td>

8、计算属性
它能监听当前的指定的依赖项的变化,从而进行相应的处理,并返回处理的结果。但是计算属性无法响应异步操作中依赖项的数据变化

// 添加计算属性
computed: {
    formatString () {
      return this.msg.substring(0, 1).toUpperCase() + this.msg.substring(1).toLowerCase()
    }
  } 

调用

<h1>{{formatString}}</h1>

9、监听器
1.侦听器的函数名称必须和你想侦听的属性名称完全一致
2.侦听器不能手动的调用,它是自动触发的
3.侦听器中一般不会返回值
4.它能响应异步操作中的数据变化

export default {
  data () {
    return {
      msg: 'hello',
      myname: 'jack'
    }
  },
  watch: {
    // 你想侦听哪个属性,就必须以这个属性做为侦听器的名称
    // newv:新的值, oldv:旧的值
    msg (newv, oldv) {
      console.log(newv, oldv)
    }
  }
}

深度监听

  • 第一种方式
users: {
    // 添加handler方法,这个函数可以侦听指定对象的属性值的变化
    // 修改这个对象的任何一个属性都会触发
    handler () {
        console.log('aa')
    },
	// 设置当前侦听为深度侦听
	deep: true
}
  • 第二种方式
// 侦听指定的属性值的变化
'users.username' (n, o) {
    console.log(n, o)
}

10、axios

get方式的无参请求

 // 获取所有分类数据
getCateList () {
    axios.get('http://127.0.0.1:4444/getCateList')
        .then((res) => {
        console.log(res)
    })
        .catch((err) => {
        console.log(err)
    })

get的带参请求
axios.get(‘/路由?参数名称=参数值&参数名称=参数值’)

  • 方式一
// 根据id获取文章详情数据
getPostById () {
    axios.get('http://127.0.0.1:4444/getPostById?id=5')
        .then((res) => {
        console.log(res)
    })
        .catch((err) => {
        console.log(err)
    })
}
  • 方式二
axios.get('http://127.0.0.1:4444/getPostById', {
    params: {
        id: 10
    }
})
    .then((res) => {
    console.log(res)
})
    .catch((err) => {
    console.log(err)
})

post请求

语法:

axios.post('路由',{数据对象})
  .then(请求成功之后的回调函数)
  .catch(请求失败之后的回调函数)
export default {
  data () {
    return {
      cate: {
        slug: '',
        name: ''
      }
    }
  },
 methods: {
	addCate () {
    	axios.post('http://127.0.0.1:4444/addCate', this.cate)
        	.then(res => {
       	 		console.log(res)
   	 		})
	        .catch(err => {
       	 	console.log(err)
    		})
		}
	}

11、promise

  • 能够解决回调地狱的问题,可以让代码不至于嵌套很深的层次
  • Promise构造函数有一个回调参数
  • 回调参数有两个参数,这两个参数都是函数,一个是操作成功的回调函数resolve,一个是操作失败的回调函数reject
var p = new Promise((resolve, reject) => {
  fs.readFile('./data/a.txt', 'utf-8', (err, data) => {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})
var p2 = new Promise((resolve, reject) => {
  fs.readFile('./data/b.txt', 'utf-8', (err, data) => {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})
var p3 = new Promise((resolve, reject) => {
  fs.readFile('./data/c.txt', 'utf-8', (err, data) => {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})
// 2.执行promise
// then里面就传入操作成功时的回调
p
  .then((res) => {
    console.log(res)
    // 将下一步需要执行的promise对象来返回:实现了一个链式编程
    return p2
  })
  .then((res) => {
    console.log(res)
    return p3
  })
  .then((res) => {
    console.log(res)
  })
// catch中就传入操作失败的回调
  .catch(err => {
    console.log(err)
  })

12、封装axios
方式1
在utils新建一个myaxios.js文件

import axios from 'axios'
// 设置全局的baseURL--基准路径
axios.defaults.baseURL = 'http://127.0.0.1:4444'
export default axios
import axios from '@/utils/myaxios.js'
axios({
    url: '/addCate',
    method: 'post',
    data:this.cate
  }).then(res => {
    console.log(res)
})
    .catch(err => {
    console.log(err)
})

方式二:更简化
在api文件夹新建cate,js文件

import axios from '@/utils/myaxios.js'

export const addCate = (data) => {
  return axios({
    url: '/addCate',
    method: 'post',
    data
  })
}

使用

import { addCate } from '@/api/cate.js'
------------------------------------
addCate(this.cate)
    .then(res => {
    console.log(res)
})
    .catch(err => {
    console.log(err)
})

13、路由router
路由的创建:vue创建路由
路由的跳转:<router-link to="/product">产品页</router-link>
获取路由参数:this.id = this.$route.params.id
监听路由变化:

// watch是来响应参数变化的
watch: {
    '$route' (to, from) {
        let id = to.params.id
        }
}

路由嵌套:

{
      name: 'product',
      // 定义参数
      path: '/product/:id',
      component: Product,
      // 使用children属性可以定义嵌套路由,它是一个数组,里面的每一个成员都一个单独的嵌套路由配置,每个配置都是一个对象,可以设置的成员与之前的路由配置完全一致
      children: [
        {
          name: 'fu',
          path: 'fu',
          component: Fu
        },
        {
          name: 'dian',
          path: 'dian',
          component: Dian
        },
        {
          name: 'shui',
          path: 'shui',
          component: Shui
        }
      ]
    }

编程式导航:

// 实现编程式导航
jump () {
    if (this.id === '1') {
        // 会将当前路由所映射的组件加载到当前父容器的router-view
        // this.$router.push({ path: `/product/${this.id}/fu` })
        this.$router.push({ name: 'fu' })
    } else if (this.id === '2') {
        this.$router.push({ name: 'dian' })
    } else if (this.id === '3') {
        this.$router.push({ name: 'shui' })
    }
}

14、父组件与子组件
1.添加一个单文件组件做为子组件

<template>
    <div class="son">
        <h2>我是子组件son</h2>
    </div>
</template>
<script>
export default {

}
</script>
<style scoped>

</style>

在父组件中

// 1.引入
import son from '@/views/Son.vue'
-----------------------------
// 2.注册
components: {
	son
}
-----------------------------
<template>
  <div class="index">
      <h1>这是index组件,它是父组件</h1>
      <!-- 3.使用 -->
      <son></son>
  </div>
</template>  

15、父子传值

父传子
父组件中为props中的成员通过动态绑定的方式赋值

<son :myname='mysonname'></son>

子组件:将这种变量定义在组件的props成员中,它一般可以定义为一个数组,里面就可以定义一个一个的变量,这种变量相当于在data中定义的变量一样来使用,props是一个单独的结构

export default {
  // 这种成员可以像data中定义的成员一样来使用,只是如果是数组的定义方式,不好设置默认值
  props: ['myname'],
  data () {
    return {
      // myname: '??'
    }
  }
}

子传父

1.在子组件中发射事件,传递数据,通过this.$emit(自定义的事件名称,传递的数据)
2.在父组件中使用子组件的位置,监听子组件发射的事件并进行处理

// 子组件添加按钮事件
<button @click="tellname">单击告诉我老爸我的女朋友的名字叫:{{mygfname}}</button>
// 子组件的按钮事件中发射事件,并传递数据
methods: {
    tellname () {
      // 发射事件.$emit可以发射事件,并传递参数
      // this.$emit(自定义的事件名称,传递的数据)
      // this发射的事件,只能由父组件进行监听
      this.$emit('getname', this.mygfname)
    }
}
----------------------------------------------------
// 父组件中使用子组件的位置  监听  子组件所发射的事件
<div class="index">
    <h1>这是index组件,我是父组件:{{myname}}</h1>
	<h2>我的儿子告诉我他找女朋友了,名字叫:{{mysongfname}}</h2>
	<!-- 3.使用 监听子组件所发射的事件,并添加事件处理函数-->
    <son :myname='mysonname' @getname='dealname'></son>
</div>
// 在事件处理函数接收子组件传递的数据,并赋值给父组件中的变量,这样,父组件就有了子组件所传递的数据
methods: {
    // 事件处理函数有一个默认的参数,这个参数就是子组件发射事件时所传递的数据
    dealname (data) {
        // 对父组件中的成员赋值
        this.mysongfname = data
    }
}

在这里插入图片描述
16、插槽

这是子组件

<div class="right">
          <!-- 定义插槽:插槽可以认为是一个结构的占位,后期你可以往这个插槽中添加任意的结构 -->
          <!-- 使用slot就可以定义插槽 -->
          <!-- 1.匿名插槽,插槽没有定义名称,那么后期在组件使用时的所有内容都会添加到匿名插槽中 -->
          <!-- <slot>默认</slot> -->
          <!-- 2.具名插槽:为插槽定义名称,后期组件使用时的结构可以指定添加到哪一个插槽中 -->
          <slot name='rightT'>aa</slot>
      </div>

这是父组件

 <mynavbar title='父子组件的传值'>
      <!-- 在使用带插槽的组件时,在组件内部添加的结构默认都会添加到插槽中 -->
      <span slot='leftT' @click='$router.back()'>返回</span>
      <span slot='rightT'>搜索</span>
    </mynavbar>

17、生命周期在这里插入图片描述
vue 的⽣命周期是: vue 实例从创建到销毁,也就是从开始创建、初始化数据、编译模板、挂载Dom!渲染、更新!渲染、卸载等⼀系列过程。

18、导航守卫
导航守卫仅仅是判断能不能进行路由的跳转,并不参与请求api的合法性

在router中的index.js文件中设置

// 添加导航守卫
// to:目标路由对象
router.beforeEach((to, from, next) => {
  // 只有访问那些需要授权的api的时候,才需要进行守卫
  if (to.path.indexOf('/personal/') === 0) {
    // 判断当前用户是否登陆过
    let token = localStorage.getItem('tokenName')
    if (token) {
      next()
    } else {
      next({ name: 'login' })
    }
  } else {
    next()
  }
})

19、拦截器
添加请求拦截器,在拦截器进行token的值的传递

// 添加请求拦截器
// config:相当于当前的请求报文
axios.interceptors.request.use(function (config) {
  console.log(config)
  // 在发送请求之前做些什么:获取token,判断是否成功的获取,如果有token则添加请求头的设置,否则不处理
  let token = localStorage.getItem('heima_40_token')
  if (token) {
    config.headers.Authorization = token
  }
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值