vue官网重温笔记

热重载:(hot-reloading)你修改页面之后,自动刷新,不用手动刷新
vue-cli的配置参考 (待仔细学习)
学习传送门:https://cli.vuejs.org/zh/config/#%E5%85%A8%E5%B1%80-cli-%E9%85%8D%E7%BD%AE
webpack配置(待仔细学习)
学习传送门:https://webpack.js.org/configuration/
过渡&动画 (要仔细学习,又是一个门)
学习传送门:https://cn.vuejs.org/v2/guide/transitions.html
通过插槽分发内容、动态组件、解析Dom模板时的注意事项
学习传送门:https://cn.vuejs.org/v2/guide/components.html#%E9%80%9A%E8%BF%87%E6%8F%92%E6%A7%BD%E5%88%86%E5%8F%91%E5%86%85%E5%AE%B9
用key管理可复用的元素
vue官网重温笔记
文章图片
image.png
切换input的时候,input就是独立的了
v-if vs v-show
传送门:https://www.jianshu.com/p/2feb8cad6abf
对象变更检测注意事项

var vm=new Vue({ data:{ userProfile:{ name:'anika' } } }) //如果想要给userProfile添加一个属性age,操作如下 Vue.set(vm.userProfile,'age',27) 或者 vm.$set(vm.userProfile,'age',27)

如果想要给已知的对象赋值多个属性可以这样操作
Object.assign({},vm.userProfile,{ age:27, favoriteColor:'vue Green' })

计算属性的应用
  • {{n}}

  • 或者
  • {{ n }}
  • data: { numbers: [ 1, 2, 3, 4, 5 ] }, methods: { even: function (numbers) { return numbers.filter(function (number) { return number % 2 === 0 }) } }

    v-for在组件中的应用

    因为li时ul内部的有效元素,所以通过is="todo-item"的方式在ul中去循环
    这样循环,组件内部中需要通过prop去接收item传递的值:例如:
    Vue.component('todo-item', { template: '\
  • \ {{ title }}\ \
  • \ ', props: ['title'] })

    事件修饰符
    传送门:https://cn.vuejs.org/v2/guide/events.html
    .stop阻止单击事件继续传播 可以阻止冒泡行为
    外部元素内部元素

    .capture修饰符事件捕获模式 如果有此修饰符会先再此先处理,然后内部的监听事件才会进行处理
    例如:
    1366777777777777777134doThis2(){ console.log('我是1') }, doThis3(){ console.log('我是2') }

    输出结果为:由外向内

    vue官网重温笔记
    文章图片
    image.png
    反之:如果没有.capture修饰符输出结果为:由内向外

    vue官网重温笔记
    文章图片
    image.png .self只有当点击的是当前本身的时候才会触发click事件 例如:
    代码如下: other在self内部,当点击self的时候,输出结果为
    1366777777777777777134selfother

    vue官网重温笔记
    文章图片
    image.png
    没有self
    注意:使用顺序, 例如:v-on:click.prevent.self 会阻止所有的点击,
    v-on:click.self.prevent会阻止对元素自身的点击
    .passive修饰符尤其能够提供移动端的性能

    不会等待scroll监听器执行完再去执行Onscroll,他会立即执行,因为.passive永远不会调用阻止默认行为的方法event.preventDefault()
    表单输入绑定
    注意 1.input中的v-mobel这样绑定,不会在输入法组合文字的过程中更新例子如下:
    如果想要即时更新的,需要使用@input去实现

    vue官网重温笔记
    文章图片
    image.png
    2.在textarea文本域中
    () //并不会生效 //应该使用v-mobel替换

    3.select选择框

    vue官网重温笔记
    文章图片
    image.png
    如果v-mobel表达式的初始值未能匹配任何选项,元素将被渲染为"未选中"状态。 在ios中,这会使用户无法选择第一个选项。因为这样的情况下,ios不会触发change事件。因此,更推荐像上面这样提供一个值为空的禁用选项

    4.修饰符 .lazy
    只有在input失去焦点或者按回车的时候才会被赋值

    插槽的使用
    vue官网重温笔记
    文章图片
    image.png 动态组件&异步组件
    动态组件的应用:
    • 多标签的界面中
    • 可以运用keep-live标签来保持原来的状态
    • 实际应用中的商品详情页面,可能会有多种状态,拼团,抢购,默认,等可以通过动态组件实现,不用好多if语句判断了

    异步组件应用:
    去请求的时候

    vue官网重温笔记
    文章图片
    image.png 定义组件名
    • kebab-case
      -PasecalCase
      注意:在使用自定义组件的时候,最好使用kebab-case的方式
    基础组件的自动化全局注册:有些不解,希望有人指教
    prop
    注意: 在子组件中通过props定义名字的使用的驼峰,在运用绑定传递的时候需要用kebab-case
    Vue.component('blog-post',{ props:['postTitle'], templete:'{{postTitle}}
    ' }) //

    prop类型
    当只在prop中写字符串的时候为数组类型 prop['title','likes','isPublished','commentIds','author'] 当在prop中写类型的时候为对象类型 prop{ title:String, likes:Number, isPublished:Boolean, commentIds:Array, author:Object }

    prop的传递有静态类型和动态类型
    //静态类型 //动态类型

    当传递一个静态类型的数字、对象、布尔类型的时候需要通过v-bind方式传递,告诉vue这不是一个字符串,这是一个javascript表达式
    //默认传递的是true ...

    单向数据流
    父级prop的更新会向下流动到子组件中,但是反过来不行。这样会防止子组件意外改变父级组件的状态。
    子组件改变父组件的值需要通过this.$emit('值',方法名)的方式更改,在组件中:方法名:父组件在定义一个方法名
    prop验证
    Vue.component('my-component', { props: { // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) propA: Number, // 多个可能的类型 propB: [String, Number], // 必填的字符串 propC: { type: String, required: true }, // 带有默认值的数字 propD: { type: Number, default: 100 }, // 带有默认值的对象 propE: { type: Object, // 对象或数组默认值必须从一个工厂函数获取 default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { // 这个值必须匹配下列字符串中的一个 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } })

    注意:那些prop会在一个组件实例创建之前进行验证,所以实例属性如(data、computed等)再default或validator函数中不可用 自定义事件
    .sync修饰符
    在有些情况下,我们可能需要对一个prop进行“双向绑定”。也就是子组件可以修改父组件的问题
    普通的this.$emit
    myShow(){ this.$emit('fun','修改的值传递') } //父组件

    使用.sync修饰符
    closeDiv() { this.$emit('update:show', false); //触发 input 事件,并传入新值 } //父组件 //当前中的valueChild就是子组件传递过来的值,不用父组件在创建方法接收 export default{ data(){ return{ valueChild:true, } }, methods:{ changeValue(){ this.valueChild = !this.valueChild } } }

    注意:.sync后面不能是表达式
    插槽:https://cn.vuejs.org/v2/guide/components-slots.html
    处理边界情况
    访问子组件实例,或子元素可以通过ref
    this.$refs.usernameInput

    注意:refs
    依赖注入
    意思就是如果子元素想要访问父组件中的方法
    在父组件中
    provide: function () { return { getMap: this.getMap } }

    在子组件中
    inject: ['getMap']

    注意:provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。
    程序化的事件监听
    • $on(eventName,eventHandler)监听一个事件
    • $once(eventName,eventHandler) 一次性监听一个事件
    • $off(eventName,eventHander) 停止监听一个事件
    应用场景:
    使用第三方库的时候,例如时间插件
    //平常我们使用 // 一次性将这个日期选择器附加到一个输入框上 // 它会被挂载到 DOM 上。 mounted: function () { // Pikaday 是一个第三方日期选择器的库 this.picker = new Pikaday({ field: this.$refs.input, format: 'YYYY-MM-DD' }) }, // 在组件被销毁之前, // 也销毁这个日期选择器。 beforeDestroy: function () { this.picker.destroy() }

    潜在问题 需要在在这个组件实例中保存这个picker
    难于程序化清理
    通过程序化监听器解决,并且可以引用使用多个时间三方库
    mounted: function () { var picker = new Pikaday({ field: this.$refs.input, format: 'YYYY-MM-DD' })this.$once('hook:beforeDestroy', function () { picker.destroy() }) }

    mounted: function () { this.attachDatepicker('startDateInput') //不同的ref元素,使用picker this.attachDatepicker('endDateInput') }, methods: { attachDatepicker: function (refName) { var picker = new Pikaday({ field: this.$refs[refName], format: 'YYYY-MM-DD' })this.$once('hook:beforeDestroy', function () { picker.destroy() }) } }

    组件之间的循环引用
    例子:
    {{ folder.name }}

    tree-folder-contents 组件
    • {{ child.name }}

    需要在注册组件的时候这样引入:使用webpack的异步import
    components: { TreeFolderContents: () => import('./tree-folder-contents.vue') }

    组件之间循环引用的问题所在:(没看懂,请大佬指教)
    • 为了解释这里发生了什么,我们先把两个组件称为 A 和 B。模块系统发现它需要 A,但是首先 A 依赖 B,但是 B 又依赖 A,但是 A 又依赖 B,如此往复。这变成了一个循环,不知道如何不经过其中一个组件而完全解析出另一个组件。为了解决这个问题,我们需要给模块系统一个点,在那里“A 反正是需要 B 的,但是我们不需要先解析 B。”
    通过v-once 创建低开销的静态组件
    ue.component('terms-of-service', { template: `Terms of Service ... a lot of static content ...` })

    注意:
    当你需要渲染大量静态内容时,极少数的情况下它会给你带来便利,除非你非常留意渲染变慢了,不然它完全是没有必要的——再加上它在后期会带来很多困惑。例如,设想另一个开发者并不熟悉 v-once 或漏看了它在模板中,他们可能会花很多个小时去找出模板为什么无法正确更新。
    混入
    【vue官网重温笔记】例子:
    var mixin = { data: function () { return { message: 'hello', foo: 'abc' } } }new Vue({ mixins: [mixin], data: function () { return { message: 'goodbye', bar: 'def' } }, created: function () { console.log(this.$data) // => { message: "goodbye", foo: "abc", bar: "def" } } })

    遇到冲突的data变量和方法名的策略
    • 同名的data变量优先选择组件内部的
    • 同名的钩子函数会合并成一个数组例如created 都会执行
    var mixin = { created: function () { console.log('混入对象的钩子被调用') } }new Vue({ mixins: [mixin], created: function () { console.log('组件钩子被调用') } })// => "混入对象的钩子被调用" // => "组件钩子被调用"

    • 值为对象的选项,例如 method、components、 directives 将被合并为同一个对象。两个兑现键值对冲突的时候优先组件内部的
    var mixin = { methods: { foo: function () { console.log('foo') }, conflicting: function () { console.log('from mixin') } } }var vm = new Vue({ mixins: [mixin], methods: { bar: function () { console.log('bar') }, conflicting: function () { console.log('from self') } } })vm.foo() // => "foo" vm.bar() // => "bar" vm.conflicting() // => "from self"

    过滤器
    {{ message | capitalize }}

    自定义过滤器:
    filters: { capitalize: function (value) { if (!value) return '' value = https://www.it610.com/article/value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } }

    或者
    Vue.filter('capitalize', function (value) { if (!value) return '' value = https://www.it610.com/article/value.toString() return value.charAt(0).toUpperCase() + value.slice(1) })new Vue({ // ... })

    当全局过滤器和局部过滤器重名时,采用局部过滤器
    //过滤器可以串联 {{ message | filterA | filterB }}//先将message传入到filterA方法中,然后再把筛选后的结果传入到filterB方法中进行筛选

    还可以这样:
    因为过滤器是javascript函数,因此可以接收参数
    {{ message | filterA('arg1', arg2) }}

    单元测试 (不明白,需要学习)
    安全
    第一原则:永远不要使用不可信任得模板
    这样得做就等于允许在应用程序中执行任意得javascript,更糟得是如果在服务端渲染得话可能导致服务器被攻破。
    例子:
    new Vue({ el: '#app', template: `` + userProvidedString + `` // 永远不要这样做 })

    vue的安全措施:https://cn.vuejs.org/v2/guide/security.html Html内容 不论使用模板还是渲染函数,内容都会被自动转义。
    例如:
    {{ userProvidedString }}

    如果userProvideString变量中包含了
    '' //被注入的恶意代码

    则会被转义成
    < script> alert(" hi" )< /script> //没有办法执行script了

    因此避免了脚本注入。该转义通过诸如textContent的浏览原生的Api完成,所以除非浏览器本身存在安全漏洞,否则不会存在安全漏洞
    Attribute(属性)绑定 道理同
    hello

    如果 userProvidedString 包含了:
    '" onclick="alert(\'hi\')'//恶意代码

    则会被转义成为如下 HTML:
    " onclick=" alert('hi')

    潜在危险
    注入url
    click me

    如果没有对url进行过滤“防止javascript:通过”则会由潜在的安全问题。有些库可以帮助解决
    sanitize-url
    https://www.npmjs.com/package/@braintree/sanitize-url
    注意:在前端进行了url过滤,那么久已经有安全问题了。用户提供的url永远需要通过后端在入库之前进行过滤。然后这个被注入的问题在每个客户端连接api时就会被阻止,包括原生移动应用。
    注入样式
    click me

    假设sanitizedUrl已经被过滤过了。但通过userProvidedStyles,恶意用户仍然可以提供css来进行“点击诈骗”。将链接的样式设置为一个透明的方框覆盖在“登陆”上,然后再把按钮做成应用中的按钮的样子。它们就可以获取一个用户真实的登陆信息。
    可以改为:
    click me

    推荐使用对象语法且只允许用户提供特定的可以安全控制的property的值
    深入响应式原理
    当把一个javascript对象传入vue实例作为data选项,vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转换为getter/setter.Object.defineProoperty是es5中一个无法shim的特性。是他们能够让vue追踪依赖。再属性被访问和修改时通知变更。
    每一个实例都对应一个watcher实例,他会再组件渲染过程中把接触过的数据属性记录为依赖。之后当依赖的setter触发时,会通知watcher,从而使它关联的组件更新渲染。

    vue官网重温笔记
    文章图片
    image.png 检测变化的注意事项
    Vue不能检测数组和对象的变化。
    对象 vue无法检测property的添加和移除。
    vue会在初始化实例时对属性执行getter/setter转化,所以属性必须在data上存在才能让vue将它转换为响应式。
    对于已经创建得vue实例,vue不允许动态添加根级别得响应式
    可以使用Vue.set(object,propertyName,value)
    例如:
    Vue.set(vm.someObject, 'b', 2)

    或者
    this.$set(this.someObject,'b',2)

    有的时候可能需要为已有对象赋值多个新属性,比如使用Object.assign()或_.extend() 。但是这样添加到对象上得新属性不会触发更新。没有被监听到,添加这些属性。可以这样,用原对象与要混合进去得对象得属性一起创建一个新的对象。
    this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

    数组 vue不能检测的数组变动:
    1.当你利用索引直接设置一个数组项时:
    vm.items[indexOfItem] = newValue

    2.当你修改数组的长度时
    vm.items.length = newLength

    举例:
    var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // 不是响应性的 vm.items.length = 2 // 不是响应性的

    可以触发更新的修改数组方式:
    Vue.set(vm.items, indexOfItem, newValue)||vm.$set(vm.items, indexOfItem, newValue)

    解决数组的长度
    vm.items.splice(newLength)

    异步更新队列
    vue在更新dom时是异步执行的。只要侦听到数据变化,vue将开启一个队列,vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被堆入到队列中一次。
    vue在内部对异步队列尝试使用原生的 Promise.then 、MutationObserver和setImmediate,如果执行环境不支持,则会采用setTimeout(fn,0)
    var vm = new Vue({ el: '#example', data: { message: '123' } }) vm.message = 'new message' // 更改数据 vm.$el.textContent === 'new message' // false(这个时候还没更改完成) //只有在执行下一个事件循环tick中更新 Vue.nextTick(function () { vm.$el.textContent === 'new message' // true })

    或者
    Vue.component('example', { template: '{{ message }}', data: function () { return { message: '未更新' } }, methods: { updateMessage: function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' this.$nextTick(function () { console.log(this.$el.textContent) // => '已更新' }) } } })

    因为$necxtTick()返回一个Promise对象,所以你可以使用新的es7的语法糖
    async/await语法完成相同的事情
    async 声明一个异步的function
    await 等待一个异步方法执行完成 再去执行下面的代码
    methods: { updateMessage: async function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' await this.$nextTick()等待 console.log(this.$el.textContent) // => '已更新' } }

    在mounted钩子函数默认是this.$el.document获取不到
    //可以这样 mounted: function () { this.$nextTick(function () { // 代码保证 this.$el 在 document 中 }) }

    注意: 在created钩子中通过$on绑定了事件,最好在组件销毁前,清除事件的监听
    beforeDestroy: function () { eventHub.$off('add-todo', this.addTodo) eventHub.$off('delete-todo', this.deleteTodo) },

    vue和其它框架的对比:https://www.jianshu.com/p/eef0a8e0dc49
    vue打包得时候总是出现好多js,希望只出现一个js
    因为页面比较多,打包成一个js的话,文件会很大。否则第一次加载的时候半天都是白屏,一般都是按需加载,打包也是根据需要进行打包

      推荐阅读