vuevue 单文件组件 style中style优先级为什么最低?

问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
请教下各位大神,怎么配置
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
额。。。这个直接在.vue里写less好像只要安装
"less": "^2.3.1", // less-loader依赖less
"less-loader": "^2.2.3"
不需要配置就能用了不过貌似需要&style lang='less'&&/style&
&template&
&div class="test"&
&div class="test-item"&&/div&
&/template&
&style lang='less'&
width: 100
height: 100
background: #f00;
.test-item {
height: 50
background: #ff0;
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:  *只有vm.$data这些被代理的属性是响应的,能够重新渲染视图
  *注意,不要在实例属性或者回调函数中(如 vm.$watch('a', newVal =& this.myMethod()))使用箭头函数。因为箭头函数绑定父级上下文,所以 this 不会像预想的一样是 Vue 实例,而且 this.myMethod是未被定义的。
  *常用的生命周期钩子:[before]created、mounted、updated、destroyed,钩子的 this 指向调用它的 Vue 实例。
  *render
  *插值:
    1.文本 {{vm.$data}} &,可以绑定data和computed, 可以使用v-once 只绑定一次不会重新渲染。
    2.纯html & v-html="rawHTML"& &--不能使用&v-html&来复合局部模板,因为 Vue 不是基于字符串的模板引擎
    3.html特性 v-bind
    4.javascript表达式 &{{}} 和v-bind 可以且只能是单个js表达式,表达式里只能访问全局变量的一个白名单
    5.指令 v- &期望所指的值是js表达式(除了v-for),操纵DOM渲染的v-用等于号“=”,操纵特性的v-用冒号“:”
    6修饰符&
    7.过滤器 &用在mustache 插值和 v-bind 表达式:&div v-bind:id="rawId | formatId"& 或者{{ message | filter2| filter3}} &,可串联
      在vm中filters属性:
        filters: {
          capitalize: function (value) {
          if (!value) return ''
          value = value.toString()
          return value.charAt(0).toUpperCase() + value.slice(1)
          }
        }
    8.计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。只要发生重新渲染,method 调用总会执行该函数。
    9.v-bind用于绑定class和 style&表达式的结果类型除了字符串之外,还可以是对象或数组。
     class:  &div class="static" & v-bind:class="{ active: isActive, 'text-danger': hasError }"& &/div&& &或者一个classObj
          --------------------------------------------------------
          &div v-bind:class="[activeClass, errorClass]"& & & & & & & & & & ===&& & & & &&
          data: {
            activeClass: 'active',
            errorClass: 'text-danger'          }
     style:  "&
          data: {
            activeColor: 'red',
            fontSize: 30
          }
          -------------------------------------------------------
        
          data: {
            styleObject: {
            color: 'red',
            fontSize: '13px'
            }
          }
     10.条件渲染:v-if &v-else &v-else-if (有更高的切换开销)。vue中元素经常会被复用,可以加key特性避免复用
            v-show只是简单切换display,不支持 &template& 语法,也不支持 v-else。
     11.v-for渲染: &
          &li v-for="(item, index) in items"&
          &div v-for="(value, key, index) in object"&
          自定义组件使用v-for:
          &my-component
          v-for="(item, index) in items"
          v-bind:item="item"
          v-bind:index="index"
          v-bind:key="item.id"          &&/my-component&
            组件有自己的作用域,所以需要v-bind将迭代数据传递给它;
           *2.2.0+ 的版本里,当在组件中使用&v-for&时,key&现在是必须的。
           *v-for&的优先级比&v-if&更高,这意味着&v-if&将分别重复运行于每个&v-for&循环中。
            *组件中加key特性,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,说到底是为了提高遍历/渲染效率。详情:/question/
      12.数组的变异方法:example1.items.push() & &会改变原始数组。
        push()        pop()        shift()        unshift()        splice()        sort()        reverse()
        非变异方法:filter(),&concat(),&slice() 返回新数组。Vue 实现了一些智能启发式方法来最大化 DOM 元素重用,,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。
        由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如:&vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:&vm.items.length = newLength
        solution:
          1.Vue.set(example1.items, indexOfItem, newValue) &或者example1.items.splice(indexOfItem, 1, newValue)
          2.example1.items.splice(newLength)
        特殊情况:我们想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。
        "&{{ n }}
(numbers)"&{{ n }}
      13.v-on监听事件时,可以传入$event 用以访问原生事件。修饰符是为了更专注于数据逻辑:
        .stop &//阻止单击事件冒泡 &
        .prevent  
        .capture &  //使用事件捕获模式
        .self &    //只当事件在该元素本身(比如不是子元素)触发时触发回调
        .once      //事件只触发一次
       14.在监听键盘事件时添加关键修饰符:
        v-on:keyup.keyCode &//比如13,keyCode为13时
        vue提供了常用别名:   
        .enter        .tab        .delete (捕获 “删除” 和 “退格” 键)        .esc        .space        .up        .down        .left        .right
        15.修饰符:
        .ctrl        .alt        .shift        .meta
        *如果要引发 keyup.ctrl,必须按下 ctrl 时释放其他的按键;单单释放 ctrl 不会引发事件。
          HTML中监听事件的好处:
        1.无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
        2.当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何自己清理它们。
        16.v-model:
        *v-model&会忽略所有表单元素的&value、checked、selected&特性的初始值。因为它会选择 Vue 实例数据来作为具体的值。你应该通过 JavaScript 在组件的&data&选项中声明初始值。
&        &&*你会发现v-model不会在 ime 输入中得到更新。如果你也想实现更新,请使用 input事件。
        *在文本区域插值(&&textarea&&/textarea&&) 并不会生效,应用&v-model&来代替
          单选按钮和复选框,v-model绑定到同一个data数组
          单选列表select&option,v-model绑定到select,在 iOS 中,这会使用户无法选择第一个选项,因为这样的情况下,iOS 不会引发 change 事件。
          solutiuon:&&option disabled value=""&请选择&/option&
      17.&Vue 只有在浏览器解析和标准化 HTML 后才能获取模版内容。尤其像这些元素&&ul&,&ol&,&table&,&select&&限制了能被它包裹的元素,而一些像&&option&&这样的元素只能出现在某些其它元素内部。solution:使用特殊的&is&属性.
      18.通过 Vue 构造器传入的data选项必须是函数。
      19.不能用&$on&侦听子组件抛出的事件,而必须在模板里直接用&v-on&绑定;v-on:click.native监听原生事件。
      20. .sync修饰符:一个自动更新父组件属性的&v-on&侦听器
        
        this.$emit('update:foo', newValue)
阅读(...) 评论()从一个奇怪的错误出发理解 Vue 基本概念 - 知乎专栏
{"debug":false,"apiRoot":"","paySDK":"/api/js","wechatConfigAPI":"/api/wechat/jssdkconfig","name":"production","instance":"column","tokens":{"X-XSRF-TOKEN":null,"X-UDID":null,"Authorization":"oauth c3cef7c66aa9e6a1e3160e20"}}
{"database":{"Post":{"":{"contributes":[{"sourceColumn":{"lastUpdated":,"description":"从数据驱动、组件化核心出发,\b探索 Vue 编程之道","permission":"COLUMN_PUBLIC","memberId":1742685,"contributePermission":"COLUMN_PUBLIC","translatedCommentPermission":"all","canManage":true,"intro":"Vue 编程思想","urlToken":"think-in-vue","id":28711,"imagePath":"4b70deef7.jpg","slug":"think-in-vue","applyReason":"0","name":"Think In Vue","title":"Think In Vue","url":"/think-in-vue","commentPermission":"COLUMN_ALL_CAN_COMMENT","canPost":true,"created":,"state":"COLUMN_NORMAL","followers":450,"avatar":{"id":"4b70deef7","template":"/{id}_{size}.jpg"},"activateAuthorRequested":false,"following":false,"imageUrl":"/4b70deef7_l.jpg","articlesCount":19},"state":"accepted","targetPost":{"titleImage":"","lastUpdated":,"imagePath":"","permission":"ARTICLE_PUBLIC","topics":[159435],"summary":"有人在学习 Vue 过程中遇到一个奇怪的问题,并为之迷惑不已——为什么这么简单的一个项目都会出错。这是一个简单到几乎不能再简单的 Vue 项目,在 index.html 的 body 中有一个 id 为 app 的 div 根元素,其中包含一个 my-component 自定义标签。&div id=\"a…","copyPermission":"ARTICLE_COPYABLE","translatedCommentPermission":"all","likes":0,"origAuthorId":0,"publishedTime":"T21:27:01+08:00","sourceUrl":"","urlToken":,"id":2381372,"withContent":false,"slug":,"bigTitleImage":false,"title":"从一个奇怪的错误出发理解 Vue 基本概念","url":"/p/","commentPermission":"ARTICLE_ALL_CAN_COMMENT","snapshotUrl":"","created":,"comments":0,"columnId":28711,"content":"","parentId":0,"state":"ARTICLE_PUBLISHED","imageUrl":"","author":{"bio":"冷眼·旁观者·清","isFollowing":false,"hash":"f58c4ffc2ee51ab3a5b3f813dd5efa3b","uid":40,"isOrg":false,"slug":"mario99","isFollowed":false,"description":"Vue.js 爱好者,极客学院 Vue.js 课程签约布道师\n奥数易学公众号","name":"Mario","profileUrl":"/people/mario99","avatar":{"id":"da8e974dc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"memberId":1742685,"excerptTitle":"","voteType":"ARTICLE_VOTE_CLEAR"},"id":563125}],"title":"从一个奇怪的错误出发理解 Vue 基本概念","author":"mario99","content":"有人在学习 Vue 过程中遇到一个奇怪的问题,并为之迷惑不已——为什么这么简单的一个项目都会出错。这是一个简单到几乎不能再简单的 Vue 项目,在 index.html 的 body 中有一个 id 为 app 的 div 根元素,其中包含一个 my-component 自定义标签。&div id=\"app\"&\n
&my-component&&/my-component&\n&/div&\nindex.js 中引入 vue 及 MyComponent 单文件组件,然后运行 new Vue。import Vue from 'Vue'\nimport MyComponent from './components/MyComponent'\n\nnew Vue({\n
el: '#app',\n
components: {\n
MyComponent\n
}\n})\nMyComponent 组件包含一个 p 元素,以插值的形式绑定显示一个包含 Hello World! 字符串的数据。项目用 webpack 打包,并使用 webpack-dev-server 启动开发服务器。webpack 配置文件内容如下:var path = require('path')\nvar HtmlWebpackPlugin = require('html-webpack-plugin')\n\nmodule.exports = {\n
entry: path.resolve(__dirname, 'index.js'),\n
output: {\n
path: path.resolve(__dirname, `dist`),\n
publicPath: '',\n
filename: 'index.js'\n
resolve: {\n
extensions: ['.js', '.vue']\n
module: {\n
loaders: [\n
test: /\\.vue$/,\n
loader: 'vue-loader'\n
test: /\\.js$/,\n
loader: 'babel-loader',\n
query: {\n
presets: ['es2015']\n
exclude: /node_modules/\n
plugins: [\n
new HtmlWebpackPlugin({\n
filename: 'index.html',\n
template: path.resolve(__dirname, 'index.html'),\n
inject: true\n
]\n}\n运行 npm run dev 并访问 http://localhost:8080/ 后,从浏览器的控制台得到如下警告信息:[Vue warn]: Failed to mount component: template or render function not defined. (found in root instance)令人百思不得其解的是,如果不使用 webpack 打包,而是直接在 HTML 文件中使用 script 标签引入 Vue.js,在 JavaScript 中手写 MyComponent 的组件选项模板,完成的页面却可以正确显示,为什么这里会提示“模板或渲染函数未定义”呢?这其实与 Vue 的两种不同的构建有关,在上述使用 webpack 打包的项目需要使用独立构建的 Vue 库,而在 node_modules/vue/package.json 文件中,已经通过 main 属性指定了通过 import Vue from 'vue' 或 require('vue') 所引入的文件是 dist/mon.js,即运行时构建的 Vue 库。直接在 HTML 文件中使用 script 标签引入的是独立构建的 Vue 库,因此没有问题。从 Vue 官方教程的
我们了解到 Vue 有两种不同的构建——独立构建和运行时构建。运行时构建删除了模板编译的功能,因此无法支持带 template 属性的 Vue 实例选项。但如果你不深入地去理解 Vue 的基本概念以及编译、挂载相关的过程,你可能仍然会很迷糊,为什么在这个项目中会有问题?说到 Vue 的概念,不得不说起 Vue 实例,这是一个使用 Vue 构造函数创建的 JavaScript 对象,创建 Vue 实例时,传递给 Vue 构造函数的参数是一个包含若干属性和方法的对象,被称为 Vue 实例选项对象,用于声明所创建的 Vue 实例对象所要挂载的目标元素、data 数据、计算属性、模板/渲染函数、实例方法以及各种生命周期钩子回调函数等选项。创建的 Vue 实例既然是一个 JavaScript 对象,那么也必然拥有属性和方法,下图是 Vue 实例所包含的属性与方法的示例:可以看出,Vue 实例的属性、方法与 Vue 选项对象的属性、方法差别很大,然而两者之间还是有关联的,比如,Vue 实例的 $el 属性是 Vue 选项对象中的 el 属性作为选择子所对应的 DOM 元素,Vue 实例的 $data 属性是 Vue 选项对象中的 data 属性(或工厂函数)经响应式处理后的对象,$options 属性则是经 Vue 构造函数处理过的 Vue 选项对象。我们通过这两个对象间关系的分析,可以加深一下对 Vue 的一些基本概念的理解——模板/渲染函数、挂载点、独立构建/运行时构建、Event Bus。首先是模板/渲染函数。Vue 官方教程的第四部分是模板语法,介绍了插值和指令,可以通过插值语法和 Vue 指令声明式地编写 Vue 模板,在教程的高级篇中,介绍了渲染函数,并说明了两者之间的关系。Vue 构造函数会将 Vue 模板编译成用于实现数据驱动的 DOM 渲染的渲染函数,开发者也可以直接手写渲染函数来发挥 JavaScript 的完全编程能力。展开 Vue 实例的 $options 属性,可以进一步看到除了 el 和 components 之外,多了若干个其他属性和方法,其中就包含编译生成的render 渲染函数。既然 Vue 构造函数在创建 Vue 实例时会将 template 编译成 render 渲染函数,但我们在调用 new Vue 时的 Vue 选项对象中并没有包含 template 属性,那么 templage 模板是从哪儿来的呢?这涉及到 Vue 选项对象中的 el 属性、template属性和 render 渲染函数的关系问题,当 Vue 选项对象中有 render 渲染函数时,Vue 构造函数将直接使用渲染函数渲染 DOM 树,当选项对象中没有 render 渲染函数时,Vue 构造函数首先通过将 template 模板编译生成渲染函数,然后再渲染 DOM 树,而当 Vue 选项对象中既没有 render 渲染函数,也没有 template 模板时,会通过 el 属性获取挂载元素的 outerHTML 来作为模板,并编译生成渲染函数。换言之,在进行 DOM 树的渲染时,render 渲染函数的优先级最高,template 次之且需编译成渲染函数,而挂载点 el 属性对应的元素若存在,则在前两者均不存在是,其 outerHTML 才会用于编译与渲染。下面我们通过创建三个不同的 Vue 实例来验证一下:html 页面 body 内容:&div class=\"app1\"&{{msg}}&/div&\n&div class=\"app2\"&{{msg}}&/div&\n&div class=\"app3\"&{{msg}}&/div&\n分别创建 Vue 实例的代码:new Vue({\n
el: '.app1',\n
msg: 'Hello, Vue.js.'\n
template: '&div&Hello, world.&/div&',\n
render: (h) =& h('div', {}, 'Hi, there.')\n})\n\nnew Vue({\n
el: '.app2',\n
msg: 'Hello, Vue.js.'\n
template: '&div&Hello, world&/div&'\n})\n\nnew Vue({\n
el: '.app3',\n
msg: 'Hello, Vue.js.'\n
}\n})\n结果如下: 通过上述说明,可以很容易地理解 Vue 的独立构建和运行时构建这两个概念,所谓独立构建是指能够将 template 模板或者从 el 挂载元素提取的模板编译成渲染函数的 Vue 库,而运行时构建则是指不能进行模板编译的 Vue 库。使用运行时库主要是为了减少体积,同时强制预编译所有模板,实现前端优化,Vue 的 npm 包也将 package.json 中的 main 指向了运行时构建 dist/mon.js,在按模块化方式引用或打包时默认使用运行时构建。什么场合使用独立构建,什么场合使用运行时构建,针对这个问题,只需要考虑清楚在项目中是否使用了模板编译功能。在包含单文件组件的项目中,使用 webpack 打包时已经将单文件组件中的模板预先编译成了渲染函数,因此一般情况下使用运行时构建的 Vue 库就可以了,但如果在使用 new Vue 创建 Vue 的根实例时,模板是从 el 挂载元素提取的,则需要使用独立构建的 Vue 库。在使用 script 标签引入 Vue.js 的项目中,任意实例选项或组件选项中包含了 template 模板属性或从 el 挂载元素提取的模板时,均需要使用独立构建的 Vue 库。要解决本文最开始的问题,需要在 webpack 配置中的 resolve 属性对象中添加如下 alias 设置:module.exports = {\n
// ... other options\n
resolve: {\n
extensions: ['.js', '.vue'],\n
alias: {\n
'vue$': 'vue/mon.js'\n
// ... other options\n}\n这里的 vue$ 表示精确匹配,由于 index.js 中还有一处大小写错误 import Vue from 'Vue',因此需要将 from 后面的 'Vue' 修改为小写的 'vue' 之后页面才能正确显示。下面再考虑一个问题:构建Vue 实例时,Vue 选项中 el 属性、template属性和 render 渲染函数是否三者必有其一?答案是不一定,可以使用不包含 el 属性、template属性和 render 渲染函数的实例选项创建 Vue 实例,事实上,如果在 Vue 实例选项中既没有设置 el 挂载点属性也没有显式调用 $mount 方法,是不会触发对 render 渲染函数(无论是手工编写还是编译生成)的检查的。比较常见的是应用场景是为实现多组件间通信而创建的 Event Bus。创建 Event Bus:import Vue from 'vue'\n\nexport const EventBus = new Vue()\n然后就可以根据需要给 Event Bus 添加事件响应:import EventBus from 'event-bus.js'\n\nEventBus.$on('customEvent1', function (...params) {\n
// ...\n})\n并在需要的时候触发事件:import EventBus from 'event-bus.js'\n\n//...\n\nEventBus.$emit('customEvent1', ...params)\n这样可以简单解决非父子组件之间通信的需求。","updated":"T13:27:01.000Z","canComment":false,"commentPermission":"anyone","commentCount":10,"collapsedCount":0,"likeCount":40,"state":"published","isLiked":false,"slug":"","lastestTipjarors":[{"isFollowed":false,"name":"young少","headline":"","avatarUrl":"/v2-aa0d1adfa3bc1_s.jpg","isFollowing":false,"type":"people","slug":"young-shao-92","bio":null,"hash":"a75cdd461ffcf0bc3ee399","uid":520000,"isOrg":false,"description":"","profileUrl":"/people/young-shao-92","avatar":{"id":"v2-aa0d1adfa3bc1","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false}],"isTitleImageFullScreen":false,"rating":"none","titleImage":"","links":{"comments":"/api/posts//comments"},"reviewers":[],"topics":[{"url":"/topic/","id":"","name":"Vue.js"}],"adminClosedComment":false,"titleImageSize":{"width":0,"height":0},"href":"/api/posts/","excerptTitle":"","column":{"slug":"think-in-vue","name":"Think In Vue"},"tipjarState":"activated","tipjarTagLine":"真诚赞赏,手留余香","sourceUrl":"","pageCommentsCount":10,"tipjarorCount":1,"annotationAction":[],"hasPublishingDraft":false,"snapshotUrl":"","publishedTime":"T21:27:01+08:00","url":"/p/","lastestLikers":[{"bio":"web和音乐","isFollowing":false,"hash":"7b4f3f1b76db254bddaeccdf","uid":16,"isOrg":false,"slug":"pa-ji-61","isFollowed":false,"description":"世界是噪音的花园","name":"帕吉","profileUrl":"/people/pa-ji-61","avatar":{"id":"0ab442ee442a07e860dd4deb215a2647","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":null,"isFollowing":false,"hash":"a19ff112d926db6eecfe92d","uid":982700,"isOrg":false,"slug":"xu-bao-shi-47","isFollowed":false,"description":"","name":"徐宝石","profileUrl":"/people/xu-bao-shi-47","avatar":{"id":"da8e974dc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":null,"isFollowing":false,"hash":"cffc5d63e953bfdb230c88","uid":002900,"isOrg":false,"slug":"wu-yi-qing-23","isFollowed":false,"description":"CS学生","name":"无亦情","profileUrl":"/people/wu-yi-qing-23","avatar":{"id":"v2-07c686a411b0de7fcc367b","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"好好干,总会发胖的","isFollowing":false,"hash":"788ad0ab65bb4f2e47ba7a","uid":64,"isOrg":false,"slug":"he-tao-hua","isFollowed":false,"description":"","name":"何韬华","profileUrl":"/people/he-tao-hua","avatar":{"id":"746a22b88","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":null,"isFollowing":false,"hash":"20ca8b09cd488","uid":423100,"isOrg":false,"slug":"jiang-hu-chuan-luan-sheng","isFollowed":false,"description":"","name":"江户川乱升","profileUrl":"/people/jiang-hu-chuan-luan-sheng","avatar":{"id":"da8e974dc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false}],"summary":"有人在学习 Vue 过程中遇到一个奇怪的问题,并为之迷惑不已——为什么这么简单的一个项目都会出错。这是一个简单到几乎不能再简单的 Vue 项目,在 index.html 的 body 中有一个 id 为 app 的 div 根元素,其中包含一个 my-component 自定义标签。&div id=\"a…","reviewingCommentsCount":0,"meta":{"previous":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"Vue.js"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"冷眼·旁观者·清","isFollowing":false,"hash":"f58c4ffc2ee51ab3a5b3f813dd5efa3b","uid":40,"isOrg":false,"slug":"mario99","isFollowed":false,"description":"Vue.js 爱好者,极客学院 Vue.js 课程签约布道师\n奥数易学公众号","name":"Mario","profileUrl":"/people/mario99","avatar":{"id":"da8e974dc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"think-in-vue","name":"Think In Vue"},"content":"Vue 核心是数据驱动和组件化,数据驱动的基础是响应式的数据绑定,首先数据通过声明式模板语法绑定到 DOM 树或组件模板中,可以实现 DOM 树的渲染,而当数据通过各种途径(用户交互、前后端数据交互、定时器……)发生变化时,响应式地更新到 DOM 树中。可以通过下面简单的代码简单理解数据响应的原理:&!DOCTYPE html&\n&html lang=\"en\"&\n&head&\n
&meta charset=\"UTF-8\"&\n
&title&Understanding Data-binding of Vue.js&/title&\n&/head&\n&body&\n
&h2&Understanding Data-binding of Vue.js&/h2&\n
Type here: \n
&input id=\"text2Edit\" type=\"text\" value=\"Hello, Vue.js.\"&\n
&div id=\"text2Disp\"&&/div&\n&/body&\n&script&\n(function () {\n
var domObj = document.getElementById('text2Disp')\n
var domEditor = document.getElementById('text2Edit')\n
domEditor.addEventListener('keyup', textEdited)\n\n
var dataObj = {}\n
var text\n\n
Object.defineProperty(dataObj, 'text', {\n
get: function () {\n
return text\n
set: function (tmpText) {\n
domObj.innerText = tmpText\n
text = tmpText\n
function textEdited() {\n
dataObj.text = text2Edit.value\n
textEdited()\n})()\n&/script&\n\n&/html&\n这段代码没有实现模板解析和数据绑定这些复杂的功能,但可以用来初步理解数据响应,通过调用 Object.defineProperty 设置 dataObj 的 text 属性的 setter,使得该数据变化时,对应的 DOM 元素的 innerText 自动更新。在 Vue 中,defineProperty 中的 setter 是由 Vue 通过编译的方式根据你所写的数据绑定的模板自动生成的,而且,对 DOM 树的更新也不是简单的针对个别 DOM 元素进行设置,而是通过调用记录了数据依赖关系的 watchers 并进一步调用渲染函数实现的。","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T10:51:14+08:00","url":"/p/","title":"\b初步理解 Vue 响应式数据绑定","summary":"Vue 核心是数据驱动和组件化,数据驱动的基础是响应式的数据绑定,首先数据通过声明式模板语法绑定到 DOM 树或组件模板中,可以实现 DOM 树的渲染,而当数据通过各种途径(用户交互、前后端数据交互、定时器……)发生变化时,响应式地更新到 DOM 树中。 可…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":0,"likesCount":0},"next":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"/50/v2-5beff85e79e7a_xl.jpg","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"Vue.js"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"冷眼·旁观者·清","isFollowing":false,"hash":"f58c4ffc2ee51ab3a5b3f813dd5efa3b","uid":40,"isOrg":false,"slug":"mario99","isFollowed":false,"description":"Vue.js 爱好者,极客学院 Vue.js 课程签约布道师\n奥数易学公众号","name":"Mario","profileUrl":"/people/mario99","avatar":{"id":"da8e974dc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"content":"题图来自网络,侵删Vue 中有若干个“语法糖”:v-model 语法糖{{ }} 插值语法糖组件注册语法糖arr.$set 语法糖后三种语法糖即使不深入理解,也可以直接应用,然而如果没有充分理解第一种语法糖,那么就可能遇到一些奇怪的问题。考虑如下需求:编写一个自定义指令,使得在文本输入框中输入的敏感词(如:f..k)自动删除,并更新通过 v-model 指令所绑定的 Vue 实例数据。自定义指令定义对象包含若干钩子函数,我们在 update 钩子函数里实现相关功能:Vue.directive('exclude', {\n
update: function (el, {value}) {\n
el.value = el.value.replace(new RegExp(value, 'gi'), '')\n
} catch (e) {\n
}\n})\n其中 {value} 是 ES6 的解构语法,可以在函数体内通过 value 直接获取参数对象的 value 属性。为避免修改指令参数对应的 Vue 实例数据时导致 new RegExp 出错,这里的赋值语句使用 try ... catch 进行错误捕获。对应模板如下:&div class=\"app\"&\n
To be excluded: &input v-model=\"excluded\"&&br&\n
&textarea v-model=\"content\" v-exclude=\"excluded\"&&/textarea&\n
{{content}}\n
&/div&\n&/div&\n其中的 excluded 和 content 均为 Vue 实例数据。然而在实际使用时,却发现,textarea 中输入的 fork 虽然被删除了,但 Vue 实例数据中的数据仍然包含了对应的单词。这是什么原因导致的呢?这涉及到 v-model 是一个语法糖这样一个事实,&input v-model=\"something\"& 等价于 &input v-bind:value=\"something\" v-on:input=\"something = $event.target.value\"&,因此在自定义指令中,通过 update 钩子函数在用户输入变化时修改 DOM 元素的 value 还不够,还需要触发 DOM 元素的 input 事件,使得通过 v-model 指令绑定的 Vue 实例数据得到更新,自定义指令修改如下:Vue.directive('exclude', {\n
update: function (el, {value}) {\n
el.value = el.value.replace(new RegExp(value, 'gi'), '')\n
el.dispatchEvent(new Event('input'))\n
} catch (e) {\n
}\n})\n考虑到 v-model 支持 lazy 修饰符,使用 lazy 修饰符时,v-model 的数据更新在 change 事件中触发,我们还需要能够针对不同的情况触发不同的事件,处理方式是在 v-exclude 指令中也增加可选的 lazy 修饰符,代码修改如下:Vue.directive('exclude', {\n
update: function(el, {value, modifiers}, vnode) {\n
el.value = el.value.replace(new RegExp(value, 'gi'), '')\n
modifiers.lazy ? el.dispatchEvent(new Event('change')) : el.dispatchEvent(new Event('input'))\n
} catch (e) {\n
}\n})\n约定若 v-model 使用了 lazy 修饰符,v-exclude 同样也要使用 lazy 修饰符。基于对 v-model 语法糖的理解,在创建如 date-picker 之类的自定义组件时,在组件中添加 value 的 prop 用于数据的传入,并在用户交互时通过 $emit 方法使用新的数据为参数触发一个 input 事件,就可以在标签中通过 v-model 双向绑定数据到子组件中了。","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T13:52:42+08:00","url":"/p/","title":"开发一个简单指令理解 Vue 的 v-model 语法糖","summary":"题图来自网络,侵删Vue 中有若干个“语法糖”: v-model 语法糖 {{ }} 插值语法糖组件注册语法糖 arr.$set 语法糖 后三种语法糖即使不深入理解,也可以直接应用,然而如果没有充分理解第一种语法糖,那么就可能遇到一些奇怪的问题。 考虑如下需求:编写一个…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":0,"likesCount":3}},"annotationDetail":null,"commentsCount":10,"likesCount":40,"FULLINFO":true}},"User":{"mario99":{"isFollowed":false,"name":"Mario","headline":"Vue.js 爱好者,极客学院 Vue.js 课程签约布道师\n奥数易学公众号","avatarUrl":"/da8e974dc_s.jpg","isFollowing":false,"type":"people","slug":"mario99","bio":"冷眼·旁观者·清","hash":"f58c4ffc2ee51ab3a5b3f813dd5efa3b","uid":40,"isOrg":false,"description":"Vue.js 爱好者,极客学院 Vue.js 课程签约布道师\n奥数易学公众号","profileUrl":"/people/mario99","avatar":{"id":"da8e974dc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"badge":{"identity":null,"bestAnswerer":null}}},"Comment":{},"favlists":{}},"me":{},"global":{"experimentFeatures":{"ge3":"ge3_9","ge2":"ge2_1","nwebStickySidebar":"sticky","nwebAnswerRecommendLive":"newVersion","newMore":"new","sendZaMonitor":"true","liveReviewBuyBar":"live_review_buy_bar_2","liveStore":"ls_a2_b2_c1_f2","homeUi2":"default","answerRelatedReadings":"qa_recommend_by_algo_related_with_article","qrcodeLogin":"qrcode","newBuyBar":"liveoldbuy","newMobileColumnAppheader":"new_header","zcmLighting":"zcm","favAct":"default","appStoreRateDialog":"close","mobileQaPageProxyHeifetz":"m_qa_page_nweb","iOSNewestVersion":"4.2.0","default":"None","wechatShareModal":"wechat_share_modal_show","qaStickySidebar":"sticky_sidebar","androidProfilePanel":"panel_b"}},"columns":{"next":{},"think-in-vue":{"following":false,"canManage":false,"href":"/api/columns/think-in-vue","name":"Think In Vue","creator":{"slug":"mario99"},"url":"/think-in-vue","slug":"think-in-vue","avatar":{"id":"4b70deef7","template":"/{id}_{size}.jpg"}}},"columnPosts":{},"columnSettings":{"colomnAuthor":[],"uploadAvatarDetails":"","contributeRequests":[],"contributeRequestsTotalCount":0,"inviteAuthor":""},"postComments":{},"postReviewComments":{"comments":[],"newComments":[],"hasMore":true},"favlistsByUser":{},"favlistRelations":{},"promotions":{},"switches":{"couldAddVideo":false},"draft":{"titleImage":"","titleImageSize":{},"isTitleImageFullScreen":false,"canTitleImageFullScreen":false,"title":"","titleImageUploading":false,"error":"","content":"","draftLoading":false,"globalLoading":false,"pendingVideo":{"resource":null,"error":null}},"drafts":{"draftsList":[],"next":{}},"config":{"userNotBindPhoneTipString":{}},"recommendPosts":{"articleRecommendations":[],"columnRecommendations":[]},"env":{"edition":{},"isAppView":false,"appViewConfig":{"content_padding_top":128,"content_padding_bottom":56,"content_padding_left":16,"content_padding_right":16,"title_font_size":22,"body_font_size":16,"is_dark_theme":false,"can_auto_load_image":true,"app_info":"OS=iOS"},"isApp":false},"sys":{},"message":{"newCount":0},"pushNotification":{"newCount":0}}

我要回帖

更多关于 vue style 的文章

 

随机推荐