Vue2.0自学笔记

一.对Vue的了解

作者:尤雨溪
渐进式框架:根据自身需求,选择框架的中的工具,VUE不强求你一次性接受并使用它的全部功能特性
Vue
数据驱动
渐进式框架
基于MVVM软件设计模式
React
开发大型项目最严谨的框架
Anagle
适用于大型项目,项目开发较为沉重,不够灵活
Vue与jquery的区别(打扫卫生)
原生JS
扫把、簸箕、拖把
Jquery
戴森吸尘器
Vue
扫地机器人(保姆)
2.MVVM(软件设计模式)
Vue.js根据这种模式设计出来
M: model数据模型
V:view 视图层
VM:View-Model视图模型
数据模型发生修改=》通知VM=》通知View视图做出响应的更新
View更改后=》通知VM=》通知Model数据模型,更新数据
3.安装
4.生命周期
vue实例从创建到挂载到更新,最后销毁,这整个流程叫做vue的生命周期

生命周期钩子函数:方便去操作当前阶段的vue实例
// 初始化构建阶段
beforeCreate  vue实例初始化完成之前,完成了vue事件、属性的初始化,但是访问不到vue实例中的data、methods
created  vue实例初始化完成,可以访问实例内部的数据和方法

// 挂载阶段
beforeMount  完成了模板的解析,但是数据没有绑定到模板上
mounted      vm.$el虚拟dom替换el Dom,完成了数据绑定/dom树渲染。

// 更新阶段
beforeUpdate 数据以及修改,虚拟dom也构建完毕,但是没有渲染到页面上
updated      更新过后的虚拟dom节点,成功渲染到页面上

// 销毁阶段 this.$destroy()
beforeDestroy vue实例销毁之前,还可以访问实例
destroyed     vue实例上绑定的事件、监听器、子组件销毁完毕,访问不到vue实例了

5.模板语法
文本插值
{{msg}} 用双大括号将data数据模型中的字段渲染到页面中
{{ msg + ‘Nihao’ }} 双大括号内部可以放js表达式
指令
v-bind:动态绑定元素上的属性
v-bind:title 简写=> :title=“title”
v-html:绑定html代码片段
富文本编辑器
有格式的内容 => 相应html代码片段
v-on:动态绑定事件
v-on:click=“clickHandler”
简写 => @click=“clickHandler”
条件渲染
v-if v- else
v-show
区别:
v-if v-else 通过控制dom节点的渲染,实现显示与隐藏
v-show 通过控制dom节点css样式中display,来实现显示与隐藏
频繁的显示与隐藏某个组件时,用v-show较好
v-if会频繁渲染dom树,占用资源,影响代码运行效率
列表渲染
v-for
使用:

    
  • {{item}}{{index}}
class绑定 :class
块级元素
块级元素
块级元素
style绑定 :style
块级元素
块级元素
块级元素
二、Vue的基本属性

1.事件机制
事件传参
@click=“handler(‘1’,$event)”
handler(id,event) {}
事件修饰符
.stop 停止事件冒泡
.prevent 阻止事件默认行为
.capture 在事件捕获阶段执行事件处理函数
.self 只当在 event.target 是当前元素自身时触发处理函数
.once 事件处理函数执行一次后解绑
.passive 滚动事件的默认行为 (即滚动行为) 将会立即触发 ,一般与scroll连用,能够提升移动端的性能
按键修饰符
.enter、.tab、.delete、.esc、.space、.up、.down、.left、.right
.ctrl、.alt、.shift、.meta
鼠标修饰符
.left、.right、.middle
2.表单
双向数据绑定
通过v-model这条指令
视图修改 => viewModel => model修改数据
model数据改变 => viewModel => view视图更新
修饰符
.lazy v-model由原来的input触发转成change事件触发
.number 将当前输入框的输出值自动转成number类型
.trim 将输出值前后的空格消除掉
表单控件
3.计算属性
可以将某个变量经过计算然后再输出

{{total}}

computed: {
total() {
return this.a + this.b
}
}
4.监听器
需要在数据变化时执行异步或开销较大的操作时,使用监听器
watch: {
// 基本数据类型
a(newVal, oldVal) {},
// 引用数据类型(如果用普通监听,只能监听到引用地址的改变)
obj: {
handler(newVal, oldVal) {},
deep: true
},
// 监听引用数据类型内部某个具体值
‘obj.username’: {
handler(newVal, oldVal) {},
deep: true
}
}

三、Vue组件机制

1.概述
组件可以拓展HTML元素,内部封装了可复用的HTML、CSS、JS代码片段。
组件类似于vue实例,组件内部有template属性,用于指定模板,
vue实例内部有el属性,用于指定模板
2.组件定义
let component = {
data() {
return {
// 返回对象值的唯一拷贝,保证复用的组件内部数据不会相互影响
msg: ‘我是组件的数据’
}
},
template:

我是组件

{{msg}}


}
3.组件注册
全局注册的组件,可以在任意vue实例或者组件内部使用
局部注册的组件,只能在当前注册的实例或者组件内部使用
类似于js中的全局变量、局部变量
1)全局注册
Vue.component(‘my-com’, component);
如果一个组件被多个其他组件调用,用全局注册较好
2)局部注册
如果一个组件在一个实例或者组件内部被多次调用,用局部注册较好

  new Vue({
    el: '#app',
    data: {},
    components: {
      'my-com': component
    }
  })

4.组件交互
1)父组件向子组件传参
父组件使用prop属性,向子组件传参


动态传参
没有:传递的常量字符串
有: 传递boolean、number、对象、数组、变量
子组件接受参数
let component = { props: ['title','msg'], } props校验 let component = { props: { title: { type: String, // 验证数据类型 required: true, // 该参数必需传递的参数 // 基本数据类型直接写在default后面 default: '你好', // 当前参数的默认值 // 引用数据类型,使用工厂函数的形式返回一个对象或者数组 default() { return { } } validator(val) { // 自定义的验证器 return val.length > 3 } } }, }
2)子组件向父组件传参
```

"

  let component = {
    data() {
      return {
        comMsg: '我是子组件数据'
      }
    },
    template:`
      
`, methods: { clickHandler() { this.$emit('son-handler', this.comMsg) } } } new Vue({ el:'#app', data: { fatherDate: '' }, methods: { fatherHandler(val) { // val就是子组件发送事件时,携带的参数this.comMsg this.fatherDate = val } }, components: { myCom: component } }) 3)单向数据流 父级的prop数据的更新,会向下流动到子组件中,反过来不行 父组件能够修改子组件中的数据,而子组件不能直接修改父组件中的数据 作用: 防止子组件意外变更状态,会影响父组件中的状态或者数据

5.插槽
1)普通插槽

  hello vue
  let com = {
    template: `
      
// 默认插槽
` } ``` 2)具名插槽 let com = { template: `
// 具名插槽
// 匿名插槽
// 具名插槽
` } 3)作用域插槽 let com = { data() { return { msg: '我是组件数据' } } template: `
// 具名插槽
// 匿名插槽
// 具名插槽
` }

6.动态组件

  // 静态组件
 // 动态组件
四、day04-可复用技术

1.混入
混入规则:
1)数据模型中的数据,会进行递归合并,出现同名属性,以组件中的数据为准
2)同名的构造函数会合并成数组,其中的函数都会调用,混入的钩子执行在前,组件的钩子执行在后
3)内部对象的合并,类似于components、methods回合并为一个对象,发生冲突时,以组件中的为准
全局混入
Vue.mixin({})
局部混入
mixins: [mixin]
2.自定义指令
指令内部有5个钩子函数
bind(){}
inserted(){}
update(){}
componentUpdated(){}
unbind(){}
每个钩子函数内部都有4个形参
el 当前指令绑定的dom对象
binding 当值绑定指令的详细信息
vNode Vue编译生成的虚拟dom节点
oldNode 上一个虚拟dom节点,只有在update和componentUpdated这两个钩子触发时,该参数才有实参
3.过滤器
使用场景
{{timestamp | fmtDate}}
v-bind=“msg | fmtText”
全局注册
Vue.filter(‘fmtDate’, (val) => {
return …val
})
局部注册
filters: {
fmtDate(val) {
return …val
}
}
4.render函数
render(createElement) {
return createElement(nodeName,props,childVnode)
}
createElement函数内部参数说明
nodeName: 标签名
props: 该元素的配置信息
‘class’、style、attrs、props、domProps、On、nativeOn
childVnode: 子虚拟节点,一般为数组,表示其子元素有多个
5.plugin插件
plugin插件需要提供一个install方法
在vue实例构建之前去调用该插件
保证创建出来的vue实例能够访问插件中的全局方法或属性
Vue.user(MyPlugin)
let vm = new Vue({})

五.Vue-Router路由管理器

vue-router是vue的一个插件,用来提供路由功能。
通过路由的改变可以动态加载组件,达到开发单页面程序的目的。
1.基本使用
1)声明组件

   let com1 = {template:`
this is com1
`
} let com2 = {template:`
this is com2
`
} let com3 = {template:`
this is com3
`
} 2)声明路由器 router是路由器对象,routes是路由列表 let router = new VueRouter({ routes: [ { path: '/a', // 路由地址 component: com1,// 对应组件 name: 'comA', // 给路由设置名字,方便使用name进行跳转 redirect: '/c', // 重定向 alias: '/coma', // 别名 }, { path: '/b', component: com2 }, { path: '/c', component: com3 }, ] }) 3)路由注册 在vue的根实例中,注册路由 let vm = new Vue({ el: '#app', router: router }) 4)路由使用 <router-link to="/a">A组件</router-link> <router-link to="/b">B组件</router-link> <router-link to="/c">C组件</router-link> // 路由视口,用来加载路由对应的组件 <router-view></router-view> 2.动态路由 1)声明 let router = new VueRouter({ routes: [ // 动态路由参数以冒号开头 { path: '/user/:username/:id', component:com1 } ] }) <router-link to="/user/zhangsan/1001"></router-link> 2)获取路由携带参数(参数值会被设置到 this.$route.params中) /user/zhangsan/1001/user/lisi/1002都将映射同一个组件, 在一个组件内部发生动态路由变化时,vue组件实例会被复用,而不会重新销毁再创建 组件内部发生动态路由变化,想要监听路由参数变化时,可以使用watch监听$route,或者使用组件内部的导航守卫 let com1 = { data() { return { id: null, username: null } }, template: ``, created() { // 在created钩子函数中,只能一次性获取携带的参数,不能够持续获取 this.id = this.$route.params.id; this.username = this.$route.params.username; }, watch() { // 使用watch监听器,可以持续监听路由器对象中,携带参数的变化 $route(to, from) { this.id = to.params.id; this.username = to.params.username; } } } 3.路由守卫 1)介绍 正如其名,vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。 每个守卫方法接收三个参数: to: Route 即将要进入的目标 路由对象 from: Route 当前导航正要离开的路由 next: Function 一定要调用该方法来 resolve 这个钩子,让路由跳转继续进行 next(): 进行管道中的下一个钩子(继续完成导航跳转) next(false): 中断当前的导航。 next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。 守卫是异步解析执行,导航在所有守卫 resolve 完之前一直处于等待中。 2)全局守卫 let router = new VueRouter({ routes: [ {...} ] }) // 全局前置守卫 router.beforeEach((to, from, next) => { .......拦截操作 next(); // next(false); }) // 全局后置守卫 router.afterEach((to, from) => { .......之后操作 }) 3)路由独享守卫 let router = new VueRouter({ routes: [ { path: '/a', component: com1, beforeEnter(to, from, next) { .......拦截操作 next(); } } ] }) 4)组件内部守卫 let com1 = { data(){ return {} }, template: ``, // 进入当前组件之前拦截 beforeRouteEnter(to, from, next) { .......拦截操作 next(); }, // 在当前组件中,路由发生改变时触发 beforeRouteUpdate(to, from, next) { .......拦截操作 next(); }, // 离开当前组件之前,触发 beforeRouteLeave(to, from, next) { .......拦截操作 next(); } } 4.嵌套路由 品字形布局:上面头部,左侧导航栏,右侧内容区域 嵌套路由的定义(children属性中定义子路由) let router = new VueRouter({ routes: [ { path: '/student', component: comStu, children: [ { path: 'grade', component: comGrade }, { path: 'register', component: comRegister }, ] } ] }) 使用 一级路由对应一个router-view 二级路由对应一个router-view 5.编程式导航 1)this.$router.push() // 在history历史栈中新增一条记录 this.$router.push({ path: '/a' }) this.$router.push({ name: 'comA' }) 路由跳转并携带参数 · 路径path跳转和query搭配使用 this.$router.push({ path: '/a', query: { username: 'zhangsan' } }) · 名字name跳转和params搭配使用 this.$router.push({ name: 'comA', params: { age: 12 } }) 参数获取 在跳转的目标组件中,只要能够访问到$route就能拿到跳转携带的参数 例如:在目标组件的created(){ console.log(this.$route.params) console.log(this.$route.query) } query传参和params传参区别 1.query传参参数保存在url地址栏中,以查询字符串的形式拼接上去 2.安全性来讲,params比较安全,query会显示在地址栏中,容易造成数据泄露 3.刷新页面时,query中的数据不受影响,而params中的数据直接消失 2)this.$router.replace() // 直接替换当前路由,不会产生新的历史记录 3)this.$router.go() // 内部接受正值或负值的整数作为参数,正数就是前进,负数就是后退(在历史记录中) 6.路由模式 1)修改路由模式 let router = new VueRouter({ // mode: 'hash', mode: 'history', // mode属性修改路由模式,默认为hash模式 routes: [] }) hash路由和history路由的区别: 1.hash路由在地址栏URL上有#,而history路由没有#,并且更精简 2.进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了 (刷新是网络请求,history路由需要后端支持)。 3.hash路由支持低版本的浏览器,而history路由是HTML5新增的API4.hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的, 所以改变hash不会重新加载页面,所以这也是单页面应用的必备。 5.history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了 pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了对历史记录进行修改的功能, 不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。 #### 六、Vuex状态管理机 1.介绍 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 应用场景: 同级别组件之间通讯 let comA = {} let comB = {} 2.基本使用: 1)state(类似于vue实例中data) 存储数据的地方,将每个vue实例中的公共变量抽取出来进行统一管理 state: { msg: 'hello vuex' } 在vue中,通过计算属性获取存储在vuex的状态,可以直接获取,也可以通过辅助函数获取 computed: { count() { return this.$store.state.count } // 或者 ...Vuex.mapState(["count"]) } 2)getters(类似于vue实例中的computed) 用于将state中静态的数据经过计算再返回 getter: { reMsg(state) { return state.msg.toUpperCase() } } 在vue中,可以通过计算属性访问 computed: { reMsg() { return this.$store.getters.reMsg } // 或者 ...Vuex.mapGetters(["reMsg"]) } 3)mutations(突变) 更改Vuex的store中的状态的唯一方法是提交 mutation,必须是同步操作。 mutation函数的第一个参数为state ,第二个参数是来接受在调用mutation的时候用户传递的实参 mutations: { SET_MSG(state, payload) { state.msg = payload } } 可以在vue生命周期钩子中提交突变或者在methods中映射突变方法 created() { // 参数一是突变方法的名字,参数二是传递的实参 this.$store.commit('SET_MSG', 'hello mutation') } methods:{ ...Vuex.mapMutations(['SET_MSG']) } 4)actions(动作) 用来存放异步请求方法,action提交的是 mutation,从而间接的变更state中的状态 actions中的异步请求接受一个形参-context(上下文对象) 可使用context.state获取state 可使用context.getters获取getters 可使用context.commit()提交突变 可使用context.dispatch()分发动作 actions: { async findAll(context) { let res = await axios.get('http://...'); // 提交突变 context.commit('SET_MSG', res.data.data) } } 可以在vue生命周期钩子中分发动作或者在methods中映射actions中的方法 created() { // 参数一是异步函数的名字,参数二可以传递实参 this.$store.dispatch('findAll') } methods:{ ...Vuex.mapActions(['findAll']) } 5)案例-定义状态机实例 let store = new Vuex.Store({ state: { msg: 'hello vuex' }, getters: { reMsg(state) { return state.msg.toUpperCase() } }, // 突变 mutations: { SET_MSG(state, payload) { state.msg = payload } }, // 动作 actions: { async findAll(context) { let res = await axios.get('http://'); // 提交突变 context.commit('SET_MSG', res.data.data) } } }) 6)通过store将状态机实例注入进去 let vm = new Vue({ el: '#app', store }) 3.辅助函数 Vuex构造函数内部提供了快捷映射数据、方法的方法 使用对象的解构,将内部的辅助函数解构出来 let { mapState, mapGetters, mapMutations, mapActions } = Vuex 使用 computed: { ...mapState(['msg']), // 状态映射 ...mapGetters(['reMsg']) // 计算属性映射 }, methods: { ...mapMutations(['SET_MSG']), // 突变映射 ...mapActions(['findAll']) // 动作映射 } 4.模块化开发 1)目的 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。 当应用变得非常复杂时,store 对象就有可能变得相当臃肿。 为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。 每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。 namespaced表示设置命名空间 2)使用 let moduleA = { namespaced: true, state() { return {} }, getters: {}, mutations: {}, actions: {} } let moduleB = { namespaced: true, state() { return {} }, getters: {}, mutations: {}, actions: {} } let store = new Vuex.Store({ modules: { // 给状态机模块重命名 a: moduleA, b: moduleB } }) let vm = new Vue({ el: '#app', data: {}, computed: { // 映射状态,第一个参数是模块的名字 ...mapState('a',['aData']), ...mapState('b',['bData']), // 映射计算属性,第一个参数是模块的名字 ...mapGetters('a',['reAData']), ...mapGetters('b',['reBData']), }, methods: { // 映射突变 ...mapMutations('a', ['SET_ADATA']), ...mapMutations('b', ['SET_BDATA']), // 映射动作 ...mapActions('a', ['findAll]) ...mapActions('b', ['query]) }, created(){ this.findAll() // 调用/执行方法 }, store: store })
七.Vue-webpack

网站 https://webpack.docschina.org
文档 https://webpack.docschina.org/concepts/
简介:本质上,webpack 是一个前端资源构建工具,用于现代 JavaScript 应用程序的静态模块打包工具。
当webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),
此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle。
全局下载包
cnpm install -g webpack webpack-cli
或者cnpm i -g webpack webpack-cli
局部下载包
初始化项目npm init -y
下载包
cnpm i --save-dev webpack webpack-cli
或者cnpm i -D webpack webpack-cli
五大模块
入口(entry)
输出(output)
loader加载器 (module)
插件(plugin)
模式(mode)
1.入口
入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
默认值是 ./src/index.js,但你可以通过在 webpack configuration 中配置 entry 属性,来指定一个(或多个)不同的入口起点。例如:
webpack.config.js
module.exports = {
//单入口
entry: ‘./path/to/my/entry/file.js’,
//多入口
entry: {
app: ‘./src/app.js’,
adminApp: ‘./src/adminApp.js’
}
};
2.输出(output)
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。
你可以通过在配置中指定一个 output 字段,来配置这些处理过程:
webpack.config.js
const path = require(‘path’);
module.exports = {
entry: ‘./path/to/my/entry/file.js’,
output: {
//filename: ‘my-first-webpack.bundle.js’,
filename: ‘./js/my-first-webpack.bundle.js’,
path: path.resolve(__dirname, ‘dist’),
}
};
path 模块是什么,它是一个 Node.js 核心模块,用于操作文件路径。resolve()用来拼接路径
3.loader
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
在更高层面,在 webpack 的配置中,loader 有两个属性:
test 属性,识别出哪些文件会被转换。
use 属性,定义出在进行转换时,应该使用哪个 loader。

  webpack.config.js
  const path = require('path');
  module.exports = {
    output: {
      filename: 'my-first-webpack.bundle.js'
    },
    module: {
      rules: [
        { 
          test: /\.html$/, 
          use: 'html-loader'
        }
      ]
    }
  };

4.插件(plugin)
loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。
想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。

webpack.config.js
  const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
  const webpack = require('webpack'); // 用于访问内置插件
  module.exports = {
    module: {
      rules: [
        { test: /\.txt$/, use: 'raw-loader' }
      ]
    },
    plugins: [
      new HtmlWebpackPlugin({template: './src/index.html'})
    ]
  };
  在上面的示例中,html-webpack-plugin 为应用程序生成 HTML 一个文件,并自动注入所有生成的 bundle。

5.模式(mode)
通过选择 development, production 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production。
6.=entry入口=======

在webpack.config.js文件中
  module.exports = {
    //单入口
    //entry:'./src/js/index.js',
    //多入口
    entry: {
      index: './src/js/index.js',
      index2: './src/js/index2.js'
    },
  }

7.=output输出=======

在webpack.config.js文件中
  const {resolve} = require('path');
  module.exports = {
    output: {
      //单出口
      //filename: './js/built-dev.js',
      //多出口
      filename: './js/[name]-built-dev.js',
      // 输出路径写绝对路径
      // __dirname nodejs的变量,代表当前文件的目录的绝对路径
      path: resolve(__dirname, 'build')
    }
  }

8.=loader module=======

在webpack.config.js文件中
  module.exports = {
    module:[
      //loader的配置
      ....
    ]
  }

9.转义js文件,排除node_modules中的文件

babel-loader
安装 cnpm i -D @babel/core @babel/preset-env babel-loader
配置
  {
    test: /\.js$/,
    exclude: /node_modules/,
    use: {
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env']
      }
    }
  }

你可能感兴趣的:(vue.js,javascript,前端)