Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue开发小结 #14

Open
willson-wang opened this issue Jan 24, 2018 · 0 comments
Open

vue开发小结 #14

willson-wang opened this issue Jan 24, 2018 · 0 comments

Comments

@willson-wang
Copy link
Owner

willson-wang commented Jan 24, 2018

  1. 在main.js里面注册store的时候,s不能大些,大些的话会无效,导致在组件里面使用mutations or actions无效,即注册的时候只能使用store,不能使用Store

  2. 在router配置文件里面,当配置子路由的时候,子路由的path前面是不需要带/的,/值需要在一级路由前面带上,因为在vue-router里面,把/开头的嵌套路径当做根路径;

  3. jquery的ajax的post请求默认为表单请求即请求头的content-type:application/x-www-form-urlencoded(简单的ajax请求,跨域请求的时候不会发起预请求),angular1.x版本的$http内的post请求默认为json格式的请求,即请求头为content-type:application/json(复杂的ajax请求,跨域请求时会发起预请求),vue的辅助插件axios的post请求,默认为json请求即请求头为content-type: application/json

  4. v-bind:href的简写:href;v-on:click的简写为@click,即自定义事件在父组件可以通过@自定义事件名or v-on自定义事件名来监听

  5. computed内的计算属性只能够动态获取简单类型值得变化,引用类型的值如果第一次是空,可以获取到最新值,如果不是空则获取不到,这个时候需要用watch来监听对象属性的变化

  6. props只能用于父子之间传递数据不能再祖孙组件之间进行传值,如果祖孙之间需要传至需要一层层的传递;

  7. this.$emit子组件向父组件传递值时,只能够通知到父组件,不能通知到祖组件,如果需要传递到祖组件则需要一层一层的传递;

  8. slot插槽的作用,插槽的作用是帮助我们向某个组件内插入不同的指定内容,通过name属性来指定内容需要被插入的插槽位置,注意插槽还可以传递作用域即可以把组件内的值通过作用域传给插槽,然后插槽内就可以使用传入的作用域内的值,需要注意的是事件不能够通过作用域传递;2.5之前的版本,带作用域的slot需要放再template内,2.5之后不再需要

<template>
     <div>
          <slot name="header"></slot>
          <slot name="body" :scope="list"></slot>
          <slot></slot>
     </div>
</template>

<child>
     <div slot="header">这是头部</div>
     <div slot="body" slot-scope="scope">{{scope.text}}</div>
     <div>这是尾部</div>
</child>
  1. computed计算属性,data内定义的属性二者之间有什么区别

    1. data内定义的属性将会转换为getter与setter,从而让 data内定义的属性能够响应数据变化;需要注意的是在组件实例之前在data内定义的对象才会被转换为getter与setter属性,才会实现响应式变化,组件内定义的是不会转换为getter与setter;data为什么是一个函数而不是一个对象是因为组件可能被用来创建多个实例(即被不同的父组件引用)。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
    2. computed计算属性的结果会被缓存,除非依赖的响应式属性(如data内定义的属性,props内传入的属性)变化才会重新计算。注意,如果实例范畴之外的依赖 (比如非响应式的 not reactive) 是不会触发计算属性更新的。它的初衷是帮助我们简化一些操作(与methods比)与节约一些性能(与watch比),计算属性默认只有getter,即获取计算属性值的方法,也可以定义setter方法,用来设置计算属性的值,在计算属性被重新赋值时进行调用,一般用来设置的当这个计算属性进行改变时,需要进行的一些操作所以在使用的时候只要考虑当前变量是否需要依赖某个项记性改变,还是说需要通过外部操作来进行改变,还是不需要改变来进行判断变量是定义成data属性内的变量还是,computed内的属性
  2. v-model详解 vue内v-model的实现方式是:value="txt" @input="txt = $event.target.value"这两段代码实现的

    1. 在父组件内使用child-input并要求给子组件的input内赋初始值,并且子组件内的值变化时,父组件绑定的对应的值也需要改变,这个argument[0]取的就是$emit(input, value)emit上来的这个value值
    2. 所以要想实现上述效果,子组件内还需要添加props:{value: {}}的属性,在子组件定义的value变量txt的set函数钩子内进行$emit('input', val)事件
    3. 注意input事件是h5新增的事件,支持ie9+浏览器,当input的内容改变时就会触发oninput事件,类似于onchange事件
    4. 还需要注意的是,oninput事件只有type="text"及type="textarea"的表单控件才有,所以要实现单选,复选等表单组件还需要使用另外的类似的方式
   基本用法如下所示
   <input type="text" v-model="txt"/> => <input :value="txt" @input="txt = $event.target.value" />
   组件之间的用法
   子组件child-input
   <input type="text" v-model="txt"/> => <input :value="txt" @input="txt = $event.target.value" />
    
   <input-child v-model="content"></input-child> => 
   <input-child :value="content" @input="content = arguments[0]></input-child>
  1. vue及angular等框架,核心思想数用数据来进行驱动,而不是dom来进行驱动,所以我们在做全选与反选时包括类似的操作应该使用数据来进行驱动而不是dom来驱动,这里需要利用data属性的双向绑定与computed属性的依赖变化

  2. 先在data里面定义一个checkList: []

  3. 在计算属性内获取到从父组件传入的v-for的列表数据内对checkList进行赋值操作,使用isChecked属性来绑定每个checkbox

  4. 在计算属性内定义当前被选中的计算属性selectCount,通过遍历,通过isChecked属性来筛选

  5. 计算属性内定义全选属性selectAll 通过get与set方法来进行全选与全不选操作,全选实现的思路是通过被选中数量计算属性与渲染当前列表的数据长度是否相等来进行判断,全不选是通过遍历及isChecked来进行设置

  6. 计算属性内定义获取当前被选中的元素数组checkedGroup,遍历,isChecked来进行判断

  7. nextTick,将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新;这里有两个概念,一个是响应式原理,一个是异步更新队列

    1. 响应式是vue框架的一个特色,它指的时数据变化之后我们可以知道具体哪个数据进行了变化,从而去更新这个数据对应的视图,实现原理就是使用es5中新增的Object.defineProperty方法,改方法可以定义对象属性的getter与setter方法,而vue就是通过setter方法的调用来判断哪个数据进行了变化,而这个监视setter函数变化就就是一个watch对象,vue框架内每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新;需要注意的时Vue 不能检测到对象属性的添加或删除(受方法的限制)。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的;然而可以通过set方法来动态设置响应式属性;
    2. 异步更新队列:就是说vue框架在处理数据变化时,遵照的是当某个响应式数据变化时,会开启一个队列,改队列会缓存统一事件循环中发生的所有数据的改变,在这一个过程中,如果同一个watcher触发多次,也之后被推入到队列一次,这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要;然后在在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作;所以也就有了nextTick钩子函数,帮助我们可以在dom更新之后再去做一些操作。一定要注意的时只有响应式数据才会遵循这种方法;
  8. 制作一个分页器的核心在两个部分,第一个就是分页器页码的生成规则,第二点就是数据总数,每页展示的条数,及当前页码这是三个关键数字;而分页器的难点就在分页器码的生成规则,需要直接好好的去总结下分页器页码的生成规则

  9. 在将 v-bind 用于 class 和 style 时,表达式结果的类型除了字符串之外,还可以是对象或数组。注意的是在组件上也是可以直接使用的,class会被添加到定义组件时的最外层元素上

字符串:class="className"
对象:class="{ active: isActive, 'text-danger': hasError }"
数组:class = "[activeClass, errorClass]"
  1. Vue 主动检测到数组变化的有三种方式,不能检测到变化的有二种方式
能检测到变化的方式
第一种成功添加的方式,Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新,splice,sort,reverse及添加与删除首尾的四个方法
this.arrsucc.push('999')

第二种方式覆盖原先的数组,非变异 (non-mutating method) 方法,例如:filter(), concat() 和 slice() 。这些不会改变原始数组,但总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:
this.arrsucc = this.arrsucc.concat(['1000'])
this.arrsucc = [...this.arrsucc, '9999']

第三种方式
this.$set(this.arrsucc, 0, 'rose')
this.$set(this.arrsucc, 1, 'jack')


不能检测到变化的方式
// 直接通过index索引来添加
this.arrerr[1] = 88

// 直接改变数组长度
this.arrerr.length = 0
  1. Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的;即有三种方式对对象的属性可以变成响应式的变化,二种方式不能进行响应式的变化
第一种是在data里面定义了的属性;
data() {
  return {
      obj: {name : 'jack'}
  }
}

第二种通过set方法来实现
this.$set(this.someObject,'b',2);

第三种通过覆盖整个对象来实现
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) 
this.someObject = {...this.someObject, { a: 1, b: 2 }

  1. v-if or v-for使用的时候可以用一个template来包裹需要操作的标签,这里的template不会被渲染出来,只是其它一个方便操作的作用,v-show的时候不能使用template标签

  2. 注意在prop进行传值时,因为HTML 特性是不区分大小写的。所以,当使用的不是字符串模板(如.html后缀的文件,字符串模板指的时.vueor其它后缀结尾的文件)时,camelCase (驼峰式命名) 的 prop 需要转换为相对应的 kebab-case (短横线分隔式命名): 而不是,所以便于将.vue后缀的文件改成.html后缀文件不出现报错的话,建议都写成kebab-case (短横线分隔式命名)

  3. 为了保证数据的单向流即父组件数据更新时,子组件对应的数据也会更新,而子组件内的数据更新时,不会影响到数据内的属性,因为JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。所以为了避免这种情况的
    出现最好的方法就是在子组件的data内声明一个新的变量来进行接收,or在计算属性内得到一个新的值

  4. 注意 prop 会在组件实例创建之前进行校验,所以在 default 或 validator 函数里,诸如 data、computed 或 methods 等实例属性or方法还无法使用

  5. 组件上的.sync 修饰符,改修饰符的作用是实现父组件内的某个变量与组件内的某个变量进行双向绑定,需要注意的是需要在子组件显示的触发this.$emit('update:foo', newValue)

<comp :foo.sync="bar"></comp>
拓展为<comp :foo="bar" @update:foo="val => bar = val"></comp>
子组件内需要显示的emit该事件this.$emit('update:foo', newValue)
  1. 单元素or组件的过渡即需要使用到动画,需要用到transition,只要给transition添加一个name,然后就可以根据这个name来定义动画了,过渡的类名总共6个,这里的v可以使用transition上的name来替换如fade-enter fade-enter-to

    1. v-enter 插入dom时触发,在下一个帧移除
    2. v-enter-active
    3. v-enter-to 插入dom完成时触发,transition/animation 完成之后移除
    4. v-leave 删除or隐藏dom时触发,在下一个帧移除
    5. v-leave-active
    6. v-leave-to 删除or隐藏dom完成时触发,transition/animation 完成之后移除
  2. 混合也就是提取出公共的数据or方法,然后混合到需要的组件内,or在全局对象上进行混合操作,添加到每个组件上,需要注意的就是一个覆盖原则,如同名钩子函数,混合之后会变成一个数组且混合对象的 钩子将在组件自身钩子 之前 调用;如methods, components 和 directives将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对;全局混合一旦使用全局混合对象,将会影响到 所有 之后创建的 Vue 实例

var mixin = {
  created: function () {
    console.log('混合对象的钩子被调用')
  }
}

new Vue({
  mixins: [mixin],
  created: function () {
    console.log('组件钩子被调用')
  }
})
  1. 移动端开发时,怎样将px转换为rem,这里使用的是postcss-px2rem-exclude loader,该loader就比postcss-px2rem多了一个可以去除不转为rem的文件目录,实现px转rem两种配置方式
1.在webpack.base.conf.js内的pugins参数内配置
plugins: [
        // loader-options-plugin 和其他插件不同,它用于将 webpack 1 迁移至 webpack 2,webpack 2 推荐的使用方式是直接传递 options 给 loader/插件
        new webpack.LoaderOptionsPlugin({
            vue: {
                postcss: function() {
                    return [px2rem({ remUnit: 75, exclude: /node_modules/ })];
                }
            }
        })
    ],

2.是在vue-loader-conf.js内进行配置
postcss: [require('postcss-px2rem-exclude')({ 'remUnit': 75, exclude: /node_modules/ })]

3.在postcssrc.js文件内添加
module.exports = {
    "plugins": {
        "postcss-import": {},
        "postcss-url": {},
        // to edit target browsers: use "browserslist" field in package.json
        "autoprefixer": {},
        'postcss-px2rem-exclude': {
            remUnit: 75,
            exclude: /node_modules/
        }
    }
}

注意的时1.2两种方式只针对vue文件,而3方式是针对所有使用了postcss-loader处理的文件

直接写px,编译后会直接转化成rem ---- 除开下面两种情况,其他长度用这个
在px后面添加/*no*/,不会转化px,会原样输出。 --- 一般border需用这个
在px后面添加/*px*/,会根据dpr的不同,生成三套代码。---- 一般字体需用这个
  1. 开发环境代理设置
在dev-server的proxyTable配置项那里进行配置,使用dev-server能够解决跨域问题的原因是,dev-server起了一个node服务器,而同源策略只限于浏览器,使用我们通过请求node服务器的接口,通过node服务器去反向代理帮我们去请求真实的接口,最终拿到数据
proxyTable: {
    '/api': { // 接口前缀
        target: 'https://xxxx.com.cn/',  // 后端接口地址
        changeOrigin: true, // 是否转接
        cookieDomainRewrite: { // 是否可以重写cookie
            "*": ""
        },
        pathRewrite: {
            '^/api': '/api' // 是否重写接口,即get('/api/basic/getlist') =>  get('/api/basic/getlist') 不变
            '/*': ''   // 接口地址不变
             '^/api': '/'   // 即get('/api/basic/getlist') =>  get('/basic/getlist') 变了
        }
    },
    '/index.php': {
        target: 'http://xxxx.cn/',
        changeOrigin: true,
        secure: false,
    }
},

// get请求,http是axios.create创建的一个实例
http.get('/index.php?r=yykf/b2c/project/get-project-list', {params})

http.get('/api/user/messages', { params })

// post请求,需要注意的是,我们直接传对象时,php后台可能因为接收不到参数报504 or 500错误,使用我们需要对参数进行stringify一下,相当于把请求头由application/json变成了表单的请求方式
http.post('/index.php?r=yykf/b2c/appointment/save', querystring.stringify(data));
@willson-wang willson-wang changed the title vue移动端开发小结 vue开发小结 Feb 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant