首页

使用 vue 1.0.3 $set 函数遇到的坑

seo达人

vue 1.0.3  中 $set 函数是动态改变或添加一个 data 中的属性值时 属性 key 不可以使用纯数字。



例如:



var app = new Vue({

     el:"#app",

     data:{

         test:{

             k1:'v1',

             k2:'v2'

         }

     },

     methods:{

         changeTestValue:function{

             // 动态改变 test 中某一属性的值

             var key = 'test.k1';  // 改变 test 属性中的 k1 的值

             this.$set(key,'changev1');  // 此处执行没有问题

            // 改变 整个 test 的值可以使用

            this.$set('test',{k1:'change-demo-v1',k2:'change-demo-v2'});   // 此处执行没有问题

            // 动态给 test 增加一个属性  k3

            this.$set('test.k3','test-add-value3');   // 此处执行没有问题

 

 

            // 此处有坑 当你的 属性为全数字的时候,则 函数无效,不报错,但是也添加不上值。

            // 例如

            this.$set('test.123','test-add-123');  // 此处执行不报错,但是也没有效果。

 

 

            // 所以在使用老版本vue的时候尽量避免 属性 key 未纯数字,或其他特殊字符。

         }

     }

});



除了这个坑以外还有另外一个坑,不过没有具体试验,

watch 监听某一值得变化,好像有点问题, 实际结果是只要 data 中的任意一个值发生变化都会被捕捉到。







最后还是使用 vue 2.x  以上版本吧,bug 少很多。







另外 $set 函数在2.x 中使用方式有所变化。







this.$set(target,key,obj);



target 对象类型,是需要赋值或修改的对象,



key  是字符串类型, 是 target 对象的属性



obj  可以是字符串,可以是对象类型,是 你要修改的或增加的值


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

转发和重定向的区别

seo达人

简单介绍

多个页面和 servlet 组成了一个基于 Java 的 web 应用程序。JSP 使用转发和重定向两种方式将控制权从一个 servlet 传递到另一个 servlet 或者 JSP。



转发(Forward)方法: 将请求从一个 servlet 转发到 web 应用程序中的另一个资源,这个资源可以是一个 servlet、JSP 页面、或者 HTML 文件。



重定向(Redirect)方法: 方法将请求重定向到另一个 web 应用程序。使用转发( Forward )方法无法完成此操作。如果一个重定向命中了同一个 web 应用程序的不同资源,那么它使用的 URL 将与原始请求的 URL 不同。如果你不想响应一个请求,你可以将请求重定向到一个不同的 URL,然后浏览器将会将你的新请求重定向到你提供的新的 URL。这篇文章详细解释了两种方式的不同之处。



什么是转发(Forward)

在基于 web 的系统或者应用程序中,通常需要在不同的资源或 JSP 之间转移控制权。例如:你如希望从电子商务网站下单,则需要先进行注册,然后才可以继续。如果你还未在他们的系统中注册,那么购物车界面可能会将控制权转移到负责注册过程的 JSP 表单。转发( Forward )方法即是用于此目的。它用于将请求从一个 JSP 转发到统一上下文中的另一个资源。



什么是重定向(Redirect)

此方法也用于转发 HTTP 请求,但与转发( Forward )不同的是:它是一个两步过程,其中重定向发生在客户端到不同的应用程序。Redirect 方法将用户重定向到新的 URL。客户端的浏览器会自动对来自服务器中的重定向表头中指定的 URL 发出新的请求。它需要与客户机进行往返通讯,因此相对来说会比转发( Forward )方法慢些。



转发(Forward)与重定向(Redirect)区别

转发(Forward)与重定向(Redirect)的描述

Forward() 方法用于将请求从一个 JSP 转发到另一个 JSP,或从一个 JSP 转发到另一个 servlet,或从一个 JSP 转发到 web 应用程序的另一个资源。控制是在容器的内部传递的,浏览器/客户机不参与此过程。Forward( )方法在 RequestDispatcher 中声明。



Sendredirect () 方法在 HttPServletResponse 中声明,用于将客户端请求重定向到不同服务器或上下文中可用的不同 URL。 通过重定向,您可以将浏览器重定向到完全不同的应用程序。



客户端是否参与转发(Forward)和重定向(Redirect)

这两种方法之间的一个关键区别是 web 容器在 Forward() 情况中处理了所有的内部进程,而且 URL 在客户端的浏览器中不会改变,因此客户端/浏览器不会参与其中,从而使它们完全不知道动作已经发生。



而在 Sendredirect () 的情况中,该方法设置适合的头部信息和正文内容以将请求重定向到不同的 URL 中,浏览器付负责将新的请求发送到客户端可见的 URL。



执行控制

当在请求时执行 Forward() 方法,当前的请求会被转发到另一个 JSP 页面,对当前 JSP 的处理也会被终止。请求可能会被转发到另一个用 Java 编程语言编写的 servlet,或者一个静态的 HTML 页面。



一个 SendRedirect() 请求只是简单告知浏览器转到另一个 URL,将执行控制发送到 web 应用程序之外。它使用一个两步的过程来指示浏览器的 URL 发出另一个将控制转发到另一个客户端的请求。



速度

Forward () 在服务器内运行,执行速度比 SendRedirect () 快。



重定向必须通过浏览器,然后等待浏览器发出新的 HTTP 请求。 一个重定向使得服务器发送 HTTP 响应状态代码 302 和一个包含新的 URL 的位置头到浏览器,并且在浏览器收到状态代码 302 之后,它对位置头中的 URL 发出一个新的请求。 这需要与客户机进行往返通信,这使得它比 Forward () 相对慢一些。



转发(Forward)和重定向(Redirect)比较图表

转发(Forward) 重定向(Redirect)

用于将请求从一个 JSP 转发到另一个 JSP,或从一个 JSP 转发到另一个 servlet,或从一个 JSP 转发到 web 应用程序的另一个资源。 用于将客户端请求重定向到不同服务器或上下文中可用的不同 URL。

Forward( )方法在 RequestDispatcher 中声明。 Sendredirect () 方法在 HttPServletResponse 中声明

不涉及客户端/浏览器,web 容器在内部处理该过程。 当客户端将 URL 作为一个新的请求后,控制权将会转移至客户端或浏览器。

当一个组件执行业务逻辑并与另一个组件共享结果时,它最有效。 当客户端应从一个页面重定向到另一页面时,此方法效果最佳。

它在服务器内运行,并且比重定向执行得更快。 它比转发慢,因为它需要与客户端进行往返通信。

使用时,原来的 URL 请求不变。 原始的 URL 请求会改变。

两种资源都必须属于同一上下文。 将请求重定向到不属于当前上下文的其它 URL。

转发(Forward)和重定向(Redirect)总结

学习转发方法和重定向方法之间的区别是 Java 开发人员最重要的部分之一。 虽然控制器可以在处理请求结束时执行转发(Forward)或重定向(Redirect)方法,但它们有自己的一组用途。



大多数情况下,您会使用 Forward () 方法,因为它比 SendRedirect () 稍微快一点,而后者实际上需要与客户机进行往返通信,使其比 Forward() 更慢。 通过重定向,你可以将浏览器导向到另一个应用程序。 这是转发无法做到的。



简而言之,当一个组件必须执行业务逻辑并与另一个组件共享结果时,转发(Forward)工作效果最好,而当客户端应该从一个页面重定向到另一个页面时,重定向(Redirect)工作效果最好。



以上内容翻译自:

Difference Between Forward and Redirect。

能力有限,还望斧正。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

vue-cli3插件初体验

seo达人

vue-cli3发布自2018年8月,距离现在还不是特别久,最好搭建项目刚好用到,所以写下这篇文章,记录一下踩坑经历。

vue的作者说过,vue-cli的本质是模

版的拉取,太多的配置导致了模版的难以维护,所以重构后的版本提供了插件的功能,一个插件对应一个功能,这样避免了多个模版,也使得cli维护性得到提高,这也是本篇文章的核心介绍内容。

我对cli3的理解是,一方面扩展了cli2的核心能力 ,一方面封装了webpack逻辑和配置。在过去要去做一个cli,通常需要阅读cli2的代码,cli2的核心模块分别是 generator,prompts,template,git-repo,并用同样的方法去做一个cli,这样其实成本不小,cli3的插件就是提供了这样一种能力,你用他的规则,去做一个npm包,并发到仓库,就可以获得这种能力。

首先,先介绍一下vue-cli3,他的发布带了哪些新功能呢?我总结一下,大概有以下5点:

1.功能丰富。这点相信大家都很好理解,他实在太好用了,模版里包含了大多数业界比较新的功能,可以一键集成typescripts等类型定义工具, eslint/tslint等语法检验工具,风格规范,prettier,husky等格式化工具,还有postcss、pwa、vue-cli-server等等。

2.提高封装性和扩展性。这点指的是vue-cli-server,在过去webpack的逻辑和配置在项目里独立维护,各个项目之间就像孤岛,vue-cli-server就像一个纽带,连接起了各个项目,为项目升级webpack提供便利性,并且通过一份配置,提供个性化配置。

这里顺带扯一下vue.config.js, 这个东西就是用来个性化配置webpack的,他提供了很多的配置项,具体可以看官方文档:

https://cli.vuejs.org/zh/config/

我们挑几个常用的来讲:

configureWebpack,这个几乎是用的比较多的,简单的方法,可以通过配置的方式配置,如下所示:

 
    
  1. module.exports = {
  2. configureWebpack: {
  3. plugins: [
  4. new MyAwesomeWebpackPlugin()
  5. ]
  6. }
  7. }复制代码


这份配置,最终会被合并到原来的配置里,不会覆盖。

复杂的方法,可以往这个字段传一个函数,如下所示:

 
  1. module.exports = {
  2. configureWebpack: config => {
  3. if (process.env.NODE_ENV === 'production') {
  4. // 为生产环境修改配置...
  5. } else {
  6. // 为开发环境修改配置...
  7. }
  8. }
  9. }复制代码

这样就可以在一个函数里做一些简单的逻辑,config是webpack config,你可以直接修改config对象,也可以返回一个对象,这个对象最终也会被合并会webpack对象。

第三种方式,是通过webpack-chain来链式调用,代码如下所示:

 
  1. module.exports = {
  2. chainWebpack: config => {
  3. config.module
  4. .rule('vue')
  5. .use('vue-loader')
  6. .loader('vue-loader')
  7. .tap(options => {
  8. // 修改它的选项...
  9. return options
  10. })
  11. }
  12. }复制代码

3.提供图形化管理界面,最所周知,gui易懂,cli,vue在降低学习门槛这方面,已经是非常好了。

通过vue ui指令,可以查看编译各个模块的情况,模块依赖情况,插件的情况,非常便于管理。

4.便捷性。vue-cli-server不仅支持项目的编译,也支持单文件的编译,具体的方法可以看官网介绍。

5.提供了cli的核心能力,也就是问询,模版渲染,文件生成这几大核心功能。具体的示意图可以看如下:


以上是cli2的核心模块,需要引用hbs,inquirer.js,metalsmit等基本模块,cli3的插件机制基本帮我们封装好了,我们只需要根据插件的规范,就可以获取这种能力。

由于有的读者可能对cli2的流程比较陌生,所以我想简单描述一下cli2的工作流程,如下图所示:


首先,cli2提供init指令,执行这个指令,会去远程拿模版文件,并拉到本地用户目录的.vue-template的文件夹,然后通过meta里问题,去问你,然后生成最终模版到你执行命令的目录。

说完vue-cli2,我们来看看vue-cli3的插件是怎么样的?

首先根据插件的位置,我们分成了cli插件,和service插件。cli的插件有完整的开发目录,所能做的事情也比较多一点,service插件是一份js文件,导出一个函数。

cli插件的目录如下所示:


具体的用发可以在官网了解到:

https://cli.vuejs.org/zh/dev-guide/plugin-dev.html#cli-%E6%8F%92%E4%BB%B6

那么他们是怎么工作的呢?

cli的代码主要在@vue/cli 下面,他的大概的流程如下图所示:


@vue/cli/bin/vue.js:

 
  1. program
  2. .command('add <plugin> [pluginOptions]')
  3. .description('install a plugin and invoke its generator in an already created project')
  4. .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
  5. .allowUnknownOption()
  6. .action((plugin) => {
  7. require('../lib/add')(plugin, minimist(process.argv.slice(3)))
  8. })
  9. program
  10. .command('invoke <plugin> [pluginOptions]')
  11. .description('invoke the generator of a plugin in an already created project')
  12. .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
  13. .allowUnknownOption()
  14. .action((plugin) => {
  15. require('../lib/invoke')(plugin, minimist(process.argv.slice(3)))
  16. })复制代码

首先,执行vue指令,会执行@vue/cli/bin/vue.js,这里定义了vue add , vue invoke,vue build,vue serve,等指令,可以看出,add指令其实是包含invoke指令的,add指令主要是安装一个包,并且触发generator.js,invoke主要是触发generator.js。

然后再来看@vue/cli/lib/add.js,

 
  1. const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : 'npm')
  2. await installPackage(context, packageManager, options.registry, packageName)复制代码
 
  1. const generatorPath = resolveModule(`${packageName}/generator`, context)
  2. if (generatorPath) {
  3. invoke(pluginName, options, context)
  4. } else {
  5. log(`Plugin ${packageName} does not have a generator to invoke`)
  6. }复制代码

add.js主要安装包,然后执行invoke模块,我们再看看invoke模块做了什么。

@vue/cli/lib/invoke.js

 
    
  1. const generator = new Generator(context, {
  2. pkg,
  3. plugins: [plugin],
  4. files: await readFiles(context),
  5. completeCbs: createCompleteCbs,
  6. invoking: true
  7. })复制代码

invoke里主要实例化generator类,然后把你的插件当成参数传给类,generator类算是vue-cli的核心类了。

@vue/cli/lib/generator.js

 
  1. plugins.forEach(({ id, apply, options }) => {
  2. const api = new GeneratorAPI(id, this, options, rootOptions)
  3. apply(api, options, rootOptions, invoking)
  4. })复制代码

这个类主要负责执行你的插件,然后把generatorapi作为参数传入插件的generator.js导出的函数。

具体的vue-cli插件的开发是怎么样的呢,我写了一个demo,用在模拟多项目的ci模版管理,通常每个项目都有一份.gitlab-ci.yml模版,所以我们一般可以抽出一个公共的ci模版来管理,这里我用cli插件来管理,真正的项目可能不具备可行性,这里我只是用来写一个例子。



目录结构大概如上所示,执行vue add foo后,就会出现propmts对话框,然后选择答案后,就会根据配置生成模版到你的根目录下。


_gitlab-ci.yml ,根据问题选择是否用私有npm仓库:

 
  1. script:
  2. <%_ if (options.config === 'npm') { _%>
  3. - nrm add companynpm http://xxx.y.cn:XXXXX/
  4. - nrm use companynpm
  5. <%_ } _%>复制代码

prompts.js,主要一些问题的设计:

 
  1. module.exports = [
  2. {
  3. name: 'config',
  4. type: 'list',
  5. message: `是否需要切换内部源:`,
  6. choices: [
  7. {
  8. name: '需要',
  9. value: 'npm',
  10. short: ''
  11. },
  12. {
  13. name: '不需要',
  14. value: 'npm',
  15. short: ''
  16. }
  17. ]
  18. }
  19. ]复制代码

generator.js 这个模块很简单,直接渲染模版

 
  1. module.exports = (api, options, rootOptions) => {
  2. // 复制并用 ejs 渲染 `./template` 内所有的文件
  3. api.render('./template')
  4. }复制代码

service插件主要放在项目本地,是一份js代码,然后导出一个函数,通过package.json配置指向这个js文件的路径,


service主要依赖的代码在@vue/cli-service里,首先先执行@vue/cli-service/bin/vue-cli-service.js文件,


 
  1. const Service = require('../lib/Service')
  2. const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
  3. .....
  4. service.run(command, args, rawArgv).catch(err => {
  5. error(err)
  6. process.exit(1)
  7. })复制代码

该文件实例化Service类,这个类是service插件的核心类,然后再执行run方法。

再来看看@vue/cli-service/lib/Service.js的代码:

首先构造函数执行resolvePlugin,把官方提供的插件和项目里的插件都加载进来,

 
  1. constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) {
  2. this.plugins = this.resolvePlugins(plugins, useBuiltIn)
  3. }复制代码

resolvePlugin这个函数主要在这里引入本地的插件:

 
  1. resolvePlugins (inlinePlugins, useBuiltIn) {
  2. // Local plugins
  3. if (this.pkg.vuePlugins && this.pkg.vuePlugins.service) {
  4. const files = this.pkg.vuePlugins.service
  5. if (!Array.isArray(files)) {
  6. throw new Error(`Invalid type for option 'vuePlugins.service', expected 'array' but got ${typeof files}.`)
  7. }
  8. plugins = plugins.concat(files.map(file => ({
  9. id: `local:${file}`,
  10. apply: loadModule(file, this.pkgContext)
  11. })))
  12. }
  13. return plugins
  14. }复制代码

run方法又会执行init方法,在该方法内部执行插件:

 
  1. init (mode = process.env.VUE_CLI_MODE) {
  2. // apply plugins.
  3. this.plugins.forEach(({ id, apply }) => {
  4. apply(new PluginAPI(id, this), this.projectOptions)
  5. }
  6. }复制代码


那么service插件要如何来实践,我们来看如下的例子:

首先在package.json配置一下,指向本地的插件my-service.js

 
  1. "vuePlugins": {
  2. "service": [
  3. "my-service.js"
  4. ]
  5. }复制代码

my-service.js的代码如下所示:

 
  1. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  2. const webpack = require('webpack');
  3. module.exports = (api, projectOptions) => {
  4. api.registerCommand(
  5. 'analyze',
  6. {
  7. description: 'start analyze server',
  8. },
  9. (args) => {
  10. // 注册 `vue-cli-service analyze`
  11. let options = projectOptions.pluginOptions.demoOptions
  12. console.log(options);
  13. // resolve webpack config
  14. const webpackConfig = api.resolveWebpackConfig();
  15. webpackConfig.plugins.push(new BundleAnalyzerPlugin());
  16. webpack(webpackConfig,(err,stats)=>{
  17. if(!err) console.log('打包成功')
  18. })
  19. },
  20. );
  21. };复制代码

该插件主要扩展vue-cli-service的指令,加了analyze指令,这个指令主要会向webpack的配置增加一个BundleAnalyzerPlugin的插件,用来分析包的大小,当然,这里也是没有太大的现实可行性的,vue-cli 提供了vue ui的Gui界面让你看到打包后各个模块的大小,或者cli的命令,vue-cli-service build --report,也能生一个报告,效果也是一样。


至此,vue-cli和service插件的使用和实现都介绍完了,如果有哪里写的不到位,希望各位大神能提出指正

vue1.0和vue2.0的区别

seo达人

一、生命周期钩子的差别



    vue1.0的生命周期如下:



    



    



    vue2.0的生命周期如下:



    



    



    用一张表格来做对比:



    



二、代码片段



    在vue1.0中可以在template编写时出现:



<template>

   <div>第一行</div>

   <div>第二行</div>

</template>

    在vue2.0中在template编写时,必须只有一个根元素,否则会报错。



<template>

   <div id='root'>

      <div>这是第一行</div>

      <div>这是第二行</div>

   </div>

</template>

三、for循环遍历数组、对象时的参数顺序的变更,遍历数组之前是(index,value),现在是(value,index);对象的之前是(key,value),现在是(value,key).



    移除了$index和$key两个隐式声明变量,以便在v-for中显式声明。



    之前的track-by已经替换为key来代替



    v-for的循环范围也发生了改变,之前v-for='item in 10',范围为0-9,现在是:1-10。







四、Props 的参数



    1、如果需要检查 prop 的值,创建一个内部的 computed 值,而不再在 props 内部去定义coerce。



    之前是:



props: {

  username: {

    type: String,

    coerce: function (value) {

      return value

        .toLowerCase()

        .replace(/\s+/, '-')

    }

  }

}

    现在改成用computed来代替:

props: {

  username: String,

},

computed: {

  normalizedUsername: function () {

    return this.username

      .toLowerCase()

      .replace(/\s+/, '-')

  }

}

    这样有一些好处:



        可以对保持原始 prop 值的操作权限。



        通过给予验证后的值一个不同的命名,强制开发者使用显式申明。



    2、twoWay参数的移除,v-bind 的 .once和.sync 修饰符 移除



            Props 现在只能单向传递。为了对父组件产生反向影响,子组件需要显式地传递一个事件而不是依赖于隐式地双向绑定。



    3、



五、计算属性



cache: false 弃用,在 Vue 未来的大版本中,计算属性的缓存验证将会被移除。把不缓存的计算属性转换为方法可以得到和之前相同的结果。    

六、Built-In 指令



v-bind 真/假值 变更;在2.0中使用 v-bind 时,只有 null, undefined,和 false 被看作是假。这意味着,0 和空字符串将被作为真值渲染。比如 v-bind:draggable="''" 将被渲染为 draggable="true";

用 v-on 监听原生事件 变更,现在在组件上使用 v-on 只会监听自定义事件 (组件用 $emit 触发的事件)。如果要监听根元素的原生事件,可以使用 .native 修饰符;

带有 debounce 的 v-model移除;

使用 lazy 或者 number 参数的 v-model ,替换;

使用内联 value的v-model 移除;

v-model with v-for Iterated Primitive Values 移除;

带有 !important 的v-bind:style 移除;

v-el 和v-ref 替换,简单起见,v-el 和 v-ref 合并为一个 ref 属性了,可以在组件实例中通过 $refs 来调用;

v-show后面使用v-else 移除。    

七、自定义指令



自定义指令 简化;    

八、过渡



transition 参数 替换,Vue 的过渡系统有了彻底的改变,现在通过使用 <transition> 和 <transition-group> 来包裹元素实现过渡效果,而不再使用 transition 属性;

可复用的过渡 Vue.transition 替换,在新的过渡系统中,可以通过模板复用过渡效果;

过渡的 stagger 参数 移除。    

九、事件



events 选项 移除,事件处理器现在在created钩子中被注册;

events 选项 移除Vue.directive('on').keyCodes 替换,新的简明配置 keyCodes 的方式是通过 Vue.config.keyCodes;

$dispatch 和 $broadcast 替换,可使用Vuex。    

十、过滤器



插入文本之外的过滤器 移除;

过滤器参数符号 变更   现在过滤器参数形式可以更好地与 js 函数调用方式一致,因此不用再用空格分隔参数,现在用圆括号括起来并用逗号分隔。

内置文本过滤器 移除,替换 json 过滤器;替换 capitalize 过滤器;替换 uppercase 过滤器;替换 lowercase 过滤器;替换 pluralize 过滤器。

双向过滤器 替换。

十一、插槽



重名的插槽 移除;

通过具名 <slot> 插入的片段不再保持 slot 的参数。请用一个包裹元素来控制样式    

十二、特殊属性



keep-alive 属性替换,不再是一个特殊属性,而是一个包裹组件。    

十三、计算插值



 属性内部的计算插值 移除;

HTML计算插值 移除,取代的是v-html指令;

单次绑定替换成v-once。  

十四、响应



vm.$watch   换成    update生命周期钩子;

Array.prototype.$set弃用,用Vue.set代替

Array.prototype.$remove 移除  用 Array.prototype.splice 替代;

Vue.set 和 Vue.delete 移除;

替换vm.$data 移除;

vm.$get 移除,可以直接取回响应数据。

十五、围绕DOM的实例方法



vm.$appendTo 移除;

vm.$before 移除;

vm.$after 移除;

vm.$remove 移除。    

十六、底层实例方法



vm.$eval 移除;

vm.$interpolate 移除;

vm.$log 移除    

十七、实例DOM选项



replace: false 移除,现在组件总是会替换掉他们被绑定的元素。为了模仿,可以用一个将要替换元素类似的元素将根组件包裹起来。    

十八、全局配置



Vue.config.debug移除,因为警告信息将默认在堆栈信息里输出;

Vue.config.async移除,异步操作现在需要渲染性能的支持;

Vue.config.delimiters移除,可以在使用自定义分隔符时避免影响第三方模板;

Vue.config.unsafeDelimiters移除,HTML的插值替换为v-html。    

十九、全局API



带el的Vue.extend移除;

Vue.elementDirective移除;

Vue.partial移除。


Vue3.0脚手架+typescript+vuex

seo达人

谈一谈vue3.0和2.0的不同及其改变,还有vue3.0脚手架的搭建



步骤:



             先卸载vue2.0的脚手架:npm  uninstall  vue-cli -g,全局卸载



            安装vue3.0的脚手架: npm  install  -g  @vue/cli,全局安装



 



入口:https://blog.csdn.net/jb_7113/article/details/89928402&nbsp;        基础一



           https://blog.csdn.net/jb_7113/article/details/89948215&nbsp;        基础二

————————————————

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

Vue 3.0 前瞻,体验 Vue Function API

seo达人

概述

Vue 2.x 及以前的高阶组件的组织形式或多或少都会面临一些问题,特别是在需要处理重复逻辑的项目中,一旦开发者组织项目结构组织得不好,组件代码极有可能被人诟病为“胶水代码”。而在 Vue 2.x 及之前的版本,解决此类问题的办法大致是下面的方案:



mixin

函数式组件

slots

笔者维护的项目也需要处理大量复用逻辑,在这之前,笔者一直尝试使用mixin的方式来实现组件的复用。有些问题也一直会对开发者和维护者造成困惑,如一个组件同时mixin多个组件,很难分清对应的属性或方法写在哪个mixin里。其次,mixin的命名空间冲突也可能造成问题。难以保证不同的mixin不用到同一个属性名。为此,官方团队提出函数式写法的意见征求稿,也就是RFC:Function-based component API。使用函数式的写法,可以做到更灵活地复用组件,开发者在组织高阶组件时,不必在组件组织上考虑复用,可以更好地把精力集中在功能本身的开发上。



注:本文只是笔者使用vue-function-api提前体验 Vue Function API ,而这个 API 只是 Vue 3.0 的 RFC,而并非与最终 Vue 3.x API 一致。发布后可能有不一致的地方。



在 Vue 2.x 中使用

要想提前在Vue 2.x中体验 Vue Function API ,需要引入vue-function-api,基本引入方式如下:



import Vue from 'vue';

import { plugin as VueFunctionApiPlugin } from 'vue-function-api';

 

Vue.use(VueFunctionApiPlugin);

基本组件示例

先来看一个基本的例子:



<template>

    <div>

        <span>count is {{ count }}</span>

        <span>plusOne is {{ plusOne }}</span>

        <button @click="increment">count++</button>

    </div>

</template>

 

<script>

import Vue from 'vue';

import { value, computed, watch, onMounted } from 'vue-function-api';

 

export default {

    setup(props, context) {

        // reactive state

        const count = value(0);

        // computed state

        const plusOne = computed(() => count.value + 1);

        // method

        const increment = () => {

            count.value++;

        };

        // watch

        watch(

            () => count.value 2,

            val => {

                console.log(`count
2 is ${val});<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br /> &nbsp; &nbsp; &nbsp; &nbsp; );<br /> &nbsp; &nbsp; &nbsp; &nbsp; // lifecycle<br /> &nbsp; &nbsp; &nbsp; &nbsp; onMounted(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(mounted);<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; // expose bindings on render context<br /> &nbsp; &nbsp; &nbsp; &nbsp; return {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count,<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plusOne,<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; increment,<br /> &nbsp; &nbsp; &nbsp; &nbsp; };<br /> &nbsp; &nbsp; },<br /> };<br /> &lt;/script&gt;<br /> 详解<br /> setup<br /> setup函数是Vue Function API 构建的函数式写法的主逻辑,当组件被创建时,就会被调用,函数接受两个参数,分别是父级组件传入的props和当前组件的上下文context。看下面这个例子,可以知道在context中可以获取到下列属性值<br /> <br /> const MyComponent = {<br /> &nbsp; &nbsp; props: {<br /> &nbsp; &nbsp; &nbsp; &nbsp; name: String<br /> &nbsp; &nbsp; },<br /> &nbsp; &nbsp; setup(props, context) {<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(props.name);<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.attrs<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.slots<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.refs<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.emit<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.parent<br /> &nbsp; &nbsp; &nbsp; &nbsp; // context.root<br /> &nbsp; &nbsp; }<br /> }<br /> value &amp; state<br /> value函数创建一个包装对象,它包含一个响应式属性value:<br /> <br /> <br /> <br /> 那么为何要使用value呢,因为在JavaScript中,基本类型并没有引用,为了保证属性是响应式的,只能借助包装对象来实现,这样做的好处是组件状态会以引用的方式保存下来,从而可以被在setup中调用的不同的模块的函数以参数的形式传递,既能复用逻辑,又能方便地实现响应式。<br /> <br /> 直接获取包装对象的值必须使用.value,但是,如果包装对象作为另一个响应式对象的属性,Vue内部会通过proxy来自动展开包装对象。同时,在模板渲染的上下文中,也会被自动展开。<br /> <br /> import { state, value } from 'vue-function-api';<br /> const MyComponent = {<br /> &nbsp; &nbsp; setup() {<br /> &nbsp; &nbsp; &nbsp; &nbsp; const count = value(0);<br /> &nbsp; &nbsp; &nbsp; &nbsp; const obj = state({<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count,<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(obj.count) // 作为另一个响应式对象的属性,会被自动展开<br /> &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp; obj.count++ // 作为另一个响应式对象的属性,会被自动展开<br /> &nbsp; &nbsp; &nbsp; &nbsp; count.value++ // 直接获取响应式对象,必须使用.value<br /> &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp; return {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count,<br /> &nbsp; &nbsp; &nbsp; &nbsp; };<br /> &nbsp; &nbsp; },<br /> &nbsp; &nbsp; template:<button @click="count++">{{ count }}</button>,<br /> };<br /> 如果某一个状态不需要在不同函数中被响应式修改,可以通过state创建响应式对象,这个state创建的响应式对象并不是包装对象,不需要使用.value来取值。<br /> <br /> watch &amp; computed<br /> watch和computed的基本概念与 Vue 2.x 的watch和computed一致,watch可以用于追踪状态变化来执行一些后续操作,computed用于计算属性,用于依赖属性发生变化进行重新计算。<br /> <br /> computed返回一个只读的包装对象,和普通包装对象一样可以被setup函数返回,这样就可以在模板上下文中使用computed属性。可以接受两个参数,第一个参数返回当前的计算属性值,当传递第二个参数时,computed是可写的。<br /> <br /> import { value, computed } from 'vue-function-api';<br /> &nbsp;<br /> const count = value(0);<br /> const countPlusOne = computed(() =&gt; count.value + 1);<br /> &nbsp;<br /> console.log(countPlusOne.value); // 1<br /> &nbsp;<br /> count.value++;<br /> console.log(countPlusOne.value); // 2<br /> &nbsp;<br /> // 可写的计算属性值<br /> const writableComputed = computed(<br /> &nbsp; &nbsp; // read<br /> &nbsp; &nbsp; () =&gt; count.value + 1,<br /> &nbsp; &nbsp; // write<br /> &nbsp; &nbsp; val =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; count.value = val - 1;<br /> &nbsp; &nbsp; },<br /> );<br /> watch第一个参数和computed类似,返回被监听的包装对象属性值,不过另外需要传递两个参数:第二个参数是回调函数,当数据源发生变化时触发回调函数,第三个参数是options。其默认行为与 Vue 2.x 有所不同:<br /> <br /> lazy:是否会在组件创建时就调用一次回调函数,与 Vue 2.x 相反,lazy默认是false,默认会在组件创建时调用一次。<br /> deep:与 Vue 2.x 的 deep 一致<br /> flush:有三个可选值,分别为 'post'(在渲染后,即nextTick后才调用回调函数),'pre'(在渲染前,即nextTick前调用回调函数),'sync'(同步触发)。默认值为'post'。<br /> // double 是一个计算包装对象<br /> const double = computed(() =&gt; count.value * 2);<br /> &nbsp;<br /> watch(double, value =&gt; {<br /> &nbsp; &nbsp; console.log('double the count is: ', value);<br /> }); // -&gt; double the count is: 0<br /> &nbsp;<br /> count.value++; // -&gt; double the count is: 2<br /> 当watch多个被包装对象属性时,参数均可以通过数组的方式进行传递,同时,与 Vue 2.x 的vm.$watch一样,watch返回取消监听的函数:<br /> <br /> const stop = watch(<br /> &nbsp; &nbsp; [valueA, () =&gt; valueB.value],<br /> &nbsp; &nbsp; ([a, b], [prevA, prevB]) =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(a is: ${a});<br /> &nbsp; &nbsp; &nbsp; &nbsp; console.log(b is: ${b});<br /> &nbsp; &nbsp; }<br /> );<br /> &nbsp;<br /> stop();<br /> 注意:在RFC:Function-based component API初稿中,有提到effect-cleanup,是用于清理一些特殊情况的副作用的,目前已经在提案中被取消了。<br /> <br /> 生命周期<br /> 所有现有的生命周期都有对应的钩子函数,通过onXXX的形式创建,但有一点不同的是,destoryed钩子函数需要使用unmounted代替:<br /> <br /> import { onMounted, onUpdated, onUnmounted } from 'vue-function-api';<br /> &nbsp;<br /> const MyComponent = {<br /> &nbsp; &nbsp; setup() {<br /> &nbsp; &nbsp; &nbsp; &nbsp; onMounted(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('mounted!');<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; onUpdated(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('updated!');<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; &nbsp; &nbsp; // destroyed 调整为 unmounted<br /> &nbsp; &nbsp; &nbsp; &nbsp; onUnmounted(() =&gt; {<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('unmounted!');<br /> &nbsp; &nbsp; &nbsp; &nbsp; });<br /> &nbsp; &nbsp; },<br /> };<br /> 一些思考<br /> 上面的详解部分,主要抽取的是 Vue Function API 的常见部分,并非RFC:Function-based component API的全部,例如其中的依赖注入,TypeScript类型推导等优势,在这里,由于篇幅有限,想要了解更多的朋友,可以点开RFC:Function-based component API查看。个人也在Function-based component API讨论区看到了更多地一些意见:<br /> <br /> 由于底层设计,在setup取不到组件实例this的问题,这个问题在笔者尝试体验时也遇到了,期待正式发布的 Vue 3.x 能够改进这个问题。<br /> <br /> 对于基本类型的值必须使用包装对象的问题:在 RFC 讨论区,为了同时保证TypeScript类型推导、复用性和保留Vue的数据监听,包装属性必须使用.value来取值是讨论最激烈的<br /> <br /> 关于包装对象value和state方法命名不清晰可能导致开发者误导等问题,已经在Amendment proposal to Function-based Component API这个提议中展开了讨论:<br /> <br /> setup() {<br /> &nbsp; &nbsp; const state = reactive({<br /> &nbsp; &nbsp; &nbsp; &nbsp; count: 0,<br /> &nbsp; &nbsp; });<br /> &nbsp;<br /> &nbsp; &nbsp; const double = computed(() =&gt; state.count * 2);<br /> &nbsp;<br /> &nbsp; &nbsp; function increment() {<br /> &nbsp; &nbsp; &nbsp; &nbsp; state.count++;<br /> &nbsp; &nbsp; }<br /> &nbsp;<br /> &nbsp; &nbsp; return {<br /> &nbsp; &nbsp; &nbsp; &nbsp; ...toBindings(state), // retains reactivity on mutations made tostate`

        double,

        increment,

    };

}

 



引入reactive API 和 binding API,其中reactive API 类似于 state API , binding API 类似于 value API。

之前使用的方法名state在 Vue 2.x 中可能被用作组件状态对象,导致变量命名空间的冲突问题,团队认为将state API 更名为 reactive 更为优雅。开发者能够写出const state = ... ,然后通过state.xxxx这种方式来获取组件状态,这样也相对而言自然一些。

value方法用于封装基本类型时,确实会出现不够优雅的.value的情况,开发者可能会在直接对包装对象取值时忘记使用.value,修正方案提出的 reactive API,其含义是创建响应式对象,初始化状态state就使用reactive创建,可保留每项属性的getter和setter,这么做既满足类型推导,也可以保留响应式引用,从而可在不同模块中共享状态值的引用。

但reactive可能导致下面的问题,需要引入binding API。 解决,如使用reactive创建的响应式对象,对其使用拓展运算符...时,则会丢失对象的getter和setter,提供toBindings方法能够保留状态的响应式。

当然,目前 Vue Function API 还处在讨论阶段,Vue 3.0 还处在开发阶段,还是期待下半年 Vue 3.0 的初版问世吧,希望能给我们带来更多的惊喜。


前端学习与工作中常用网站推荐

seo达人

一.视频学习网站

1.慕课网(我的最爱,里面有很多免费的视频)



2.腾讯课堂 



。。。



当然还有很多其他的视频学习网站,但我觉得就这两个就够质够量了。



二.前端免费模板下载

1.html5tricks



有很多有趣的小程序



2.源码之家 



各类模板灰常之多,不过也有很多广告



3.代码家园



整个网站看起来舒服,广告很少



4.模板之家



广告较多



5.魔客吧



有些要money



6.站长之家



。。。



模板网站就推荐这些吧,差不多够用了。当然,我们下载这些模板的目的不是为了抄袭,而是为了参考学习。(手动滑稽:) )



三.图片图标logo素材

1.标志在线



免费设计logo



2.阿里巴巴矢量图标



图标特别多,而且基本上都是免费的



3.iconmonstr



免费图标下载



4.懒人图库



素材很多,不知道要不要钱



5.loading.io



看名字就知道是下什么的了吧



6.preloaders



进度条下载,有些要钱还是dollar,不过也有很多免费的



。。。



好吧,就这些。



四.其他

1.JS格式化



如果你的编辑器不支持格式化js代码的话可以试试



2.css代码兼容



css代码复制上去,自动会帮你生成兼容的css代码,是不是很厉害!不过兼容IE几我也不太清楚,你们自己去看看吧



3.配色



这是给你网站配色的,有兴趣的可以了解下



4.html、css、js压缩,js多文件合并



es6代码需先转es5再压缩,当然,也可以使用fis3构建压缩html,css,js;fis3还可以将图片转成webp格式(ios有兼容问题)



5.图片压缩



基本上是无损压缩,效果很不错



6.图片转换



转webp格式图片



7.雪碧图 (似乎访问不了了)



选中雪碧图中的图片,自动生成css代码。如:background: url('imgs/example.png') no-repeat -433px -51px;width: 33px;height: 33px;



8.html在线编辑工具



可以在线运行html代码



9.rgb,rgba,十六进制等颜色相互转换



10.HTML特殊字符编码对照表



11.改图宝



修改图片尺寸,生成二维码,生成印章,图片加水印...



。。。



 



最后,再推荐一些比较好的书



《css世界》、《ES6标准入门》阮一峰、《JavaScript权威指南》、《JavaScript高级程序设计》(红皮书)、《你不知道的JavaScript 上中下册》

————————————————


el-table + el-form实现可编辑表格字段验证

seo达人

表格输入信息很常见,因此表格的验证也很必要,el-form提供了输入框验证.可以和表格结合起来用,使用效果
 
 
HTML:
<div class="table_box">
  <el-button type="primary" class="submit_btn" @click="addTable">添加</el-button> <!-- 如果不想展示错误提示信息,可以加上show-message参数 --> <el-form :model="productRuleForm" ref="productRuleForm" :rules="productRuleForm.rules" :show-message="false">
    <el-table
      :data="productRuleForm.tableData" border
      style="width: 100%">
      <el-table-column
        prop="date" label="日期" width="180">
        <template slot-scope="scope"> <!-- prop的规则: 在普通的form表单中是一个对象,prop是对象的属性. 表格是由多个对象组成的数组,在写prop是需要根据索引给值.这里的tableData就相当于对象的属性 !-->
        <!-- rules也要单独给 --> <el-form-item :prop="'tableData.' + scope.$index + '.date'"
            :rules='productRuleForm.rules.date'>
            <el-date-picker
              v-model="scope.row.date" value-format="yyyy-MM-dd" placeholder="选择日期">
            </el-date-picker>
          </el-form-item>
        </template>
      </el-table-column>
      <el-table-column
        prop="name" label="姓名" width="180">
        <template slot-scope="scope">
          <el-form-item
            :prop="'tableData.' + scope.$index + '.name'" :rules='productRuleForm.rules.name'>
            <el-input v-model="scope.row.name"></el-input>
          </el-form-item>
        </template>
      </el-table-column>
      <el-table-column
        prop="phone" label="电话">
        <template slot-scope="scope">
          <el-form-item
            :prop="'tableData.' + scope.$index + '.phone'" :rules='productRuleForm.rules.phone'>
            <el-input v-model="scope.row.phone"></el-input>
          </el-form-item>
        </template>
      </el-table-column>
      <el-table-column
        prop="address" label="地址">
        <template slot-scope="scope">
          <el-form-item
            :prop="'tableData.' + scope.$index + '.address'" :rules='productRuleForm.rules.address'>
            <el-input v-model="scope.row.address"></el-input>
          </el-form-item>
        </template>
      </el-table-column>
    </el-table>
  </el-form>
  <el-button type="primary" class="submit_btn" @click="submit">提交</el-button>
</div>

 


        

 

js:

data () { return {
      productRuleForm: {
        tableData: [{
          date: '',
          name: '',
          phone: '',
          address: '' }],
        rules: {
          date: [{ required: true, message: '请选择日期', trigger: 'change' }],
          name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
          phone: [{ required: true, message: '请输入电话号码', trigger: 'blur' }],
          address: [{ required: true, message: '请输入地址', trigger: 'blur' }]
        }
      }
    }
  },
 methods: { // 添加一行  addTable () { this.productRuleForm.tableData.push({
        date: '',
        name: '',
        phone: '',
        address: '' })
    }, // 提交数据  submit () { this.$refs['productRuleForm'].validate((valid) => { if (valid) {

        }
      })
    } 
            

}

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

element ui在table中放入input且实现验证

seo达人

<template>

  <div class="app-container" style="overflow: auto;">

    <el-table

      :data="list"

      size="small"

      element-loading-text="Loading"

      border

      highlight-current-row

    >

      <el-table-column label="会员账号">

        <template slot-scope="scope">

          <el-form :model="scope.row" :rules="rules">

            <el-form-item prop="login">

              <el-input v-show="true" v-model="scope.row.login" placeholder="请输入会员账号"/>

            </el-form-item>

          </el-form>

        </template>

      </el-table-column>

      <el-table-column label="真实姓名">

        <template slot-scope="scope">

          <el-form :model="scope.row" :rules="rules">

            <el-form-item prop="real_name">

              <el-input v-show="true" v-model="scope.row.real_name" placeholder="请输入真实姓名"/>

            </el-form-item>

          </el-form>

        </template>

      </el-table-column>

      <el-table-column label="会员昵称">

        <template slot-scope="scope">

          <el-form :model="scope.row" :rules="rules">

            <el-form-item prop="nickname">

              <el-input v-show="true" v-model="scope.row.nickname" placeholder="请输入会员昵称"/>

            </el-form-item>

          </el-form>

        </template>

      </el-table-column>

      <el-table-column label="会员手机">

        <template slot-scope="scope">

          <el-form :model="scope.row" :rules="rules">

            <el-form-item prop="mobile">

              <el-input v-show="true" v-model="scope.row.mobile" placeholder="请输入手机号码"/>

            </el-form-item>

          </el-form>

        </template>

      </el-table-column>

      <el-table-column label="操作">

        <template slot-scope="scope">

          <el-form ref="scope.row" :model="scope.row">

            <el-form-item>

              <el-button @click="handleSubmit(scope.$index,scope.row)">重试</el-button>

            </el-form-item>

          </el-form>

        </template>

      </el-table-column>

    </el-table>

  </div>

</template>

<script>

import { retry } from '@/api/table'

import { validateName } from '@/utils/validate'

import { validateMobile } from '@/utils/validate'

 

export default {

  data() {

    // validator

    const validateNameInput = (rule, value, callback) => {

      if (!value) {

        return callback(new Error('此项必填!'))

      } else {

        callback()

      }

    }

    const validateMobileInput = (rule, value, callback) => {

      if (!value) {

        return callback(new Error('手机号码必填!'))

      } else if (!validateMobile(value)) {

        return callback(new Error('请填写正确的手机号码格式!'))

      } else {

        callback()

      }

    }

 

    return {

      list: [],

      // input框失焦校验

      rules: {

        nickname: [{ validator: validateNameInput, trigger: 'blur' }],

        real_name: [{ validator: validateNameInput, trigger: 'blur' }],

        mobile: [{ validator: validateMobileInput, trigger: 'blur' }],

        login: [{ validator: validateNameInput, trigger: 'blur' }]

      }

    }

  },

  created() {

    this.fetchData()

  },

  methods: {

    fetchData() {

      const errorData = JSON.parse(this.$route.query.errorData)

      this.list = JSON.parse(errorData)

    },

    handleSubmit(index, row) {

      // 提交校验

      if (validateName(row.login) && validateName(row.real_name) && validateName(row.nickname) && validateMobile(row.mobile)) {

       //数据提交和错误catch

    }

  }

}

</script>

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

Vue一些注意点

seo达人

1.Method与计算属性computed的区别

区别在于method每次都执行函数,而computed基于依赖缓存,只要相关值不变,那么就不必再执行函数。



下面,注意Date不是响应式依赖:



computed: {

  now: function () {

    return Date.now()

  }

}

所以使用计算属性



2.v-if与v-show

v-if 是真实的条件渲染,因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件。



v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——在条件第一次变为真时才开始局部编译(编译会被缓存起来)。



相比之下, v-show 简单得多——元素始终被编译并保留,只是简单地基于 CSS 切换。



一般来说, v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换使用 v-show 较好,如果在运行时条件不大可能改变则使用 v-if 较好。



令,v-show不支持template语法。



3.v-for

可以v-for="item in items"也可以of



还有可选第二参数作为前项的索引:



<li v-for="(item, index) in items">

也可以用模板渲染父节点或模板,来渲染多个子块。



<ul id="repeat-object" class="demo">

     <li v-for="value in object">

       {{ value }}

     </li>

  </ul>

new Vue({

       el: '#repeat-object',

       data: {

       object: [

        {FirstName: 'John'},

        {LastName: 'Doe'},

        {Age: 30}

      ]

    }

  })

写成这样,输出:



{ "FirstName": "John" }

{ "LastName": "Doe" }

{ "Age": 30 }

将object从数组变为如下:



object: {



FirstName: 'John',



LastName: 'Doe',



Age: 30



}



那么输出:



John

Doe

30

此时直接指向的是值了。



还有三参数:v-for="(value, key, index) in object"

还可以用整数,输出10个数字:



<div id="haha">

  <span v-for="n in 10">{{ n }}</span>

</div>

var t=1,n=0;

new Vue({

 el: '#haha',

 data: {

 object: {

 n:n+t

  }

 }

})

很好的例子

4.一些数组方法

push():在末尾添加一个或多个元素,并返回新长度

pop():删除并返回最后一个元素

shift():删除并返回第一个元素

unshift():数组开头添加一个或多个元素,并返回新长度

splice():删除或替换元素,返回被删除元素。splice(index,number,new ele),用new ele 替换index开始的number个元素

sort()

reverse()





5.类似v-on:click(含参)的注意点

<button v-on:click="warn('Form cannot be submitted yet.', $event)">Submit</button>

methods: {

  warn: function (message, event) {

    // 现在我们可以访问原生事件对象

    if (event) event.preventDefault()

    alert(message)

  }

}

如上,可以传入原生DOM对象。

阻止冒泡还有其他方法,即在v-on上使用事件修饰符。常见事件修饰符有:

<!-- 阻止单击事件冒泡 -->

<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->

<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联  -->

<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->

<form v-on:submit.prevent></form>

<!-- 添加事件侦听器时使用事件捕获模式 -->

<div v-on:click.capture="doThis">...</div>

<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->

<div v-on:click.self="doThat">...</div>

<!-- 只会触发一次点击 -->

<a v-on:click.once="doThis"></a>

有事件修饰符,还有键盘修饰符。

<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->

<input v-on:keyup.13="submit">

<input v-on:keyup.enter="submit">

又新增了按键修饰符,和组合键修饰:

<!-- Alt + C -->

<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->

<div @click.ctrl="doSomething">Do something</div>

6.神奇的v-model

神奇之处在于会根据控件形式自动选取方法更新元素。

例子

<div id="che">

      <select v-model="sele"  multiple>

         <option v-for="op in ops" v-bind:value="op.index">{{op.va}}</option>

         

      </select>

      <span>{{sele}}</span>

    </div>

new Vue({

          el: '#che',

          data: {

            sele: [],

            ops:[

                {index:1,va:"s"},

                {index:2,va:"ss"},

                {index:3,va:"ssr"}

            ]

          }

        })

若option里绑定value,则会将value值按所选中的放在数组sele开头。

若没有绑定value,会将{{op.va}}当做value。若写为{{op.index}}则将index当做value。



蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档