Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API; Vue.js是一个构建数据驱动的Web界面的库。 Vue.js是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和 Vue生态系统支持的库开发的复杂单页应用。数据驱动+组件化的前端开发。 简而言之:Vue.js是一个构建数据驱动的 web 界面的渐进式框架。Vue.js 的目标是通过尽可能简单的 API实现响应的数据绑定和组合的视图组件。核心是一个响应的数据绑定系统。
MVVM 是 Model-View-ViewModel 的缩写。mvvm 是一种设计思想。Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象。
当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
简洁:页面由HTML模板+Json数据+Vue实例组成 数据驱动:自动计算属性和追踪依赖的模板表达式 组件化:用可复用、解耦的组件来构造页面 轻量:代码量小,不依赖其他库 快速:精确有效批量DOM更新 模板友好:可通过npm,bower等多种方式安装,很容易融入
首先我是直接从写网页开始练习的,随便创建一个HTML文件,然后在中间直接用<script>引入
对于制作原型或学习,你可以这样使用最新版本:
<script src="https://unpkg.com/vue/dist/vue.js"></script>或者用一个链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>然后就能开始练习了,我是在这里学习的
学习过程中发现 Elements in iteration expect to have ‘v-bind:key’ directives的报错 原因:VSCode中ESLint的功能,对vue进行了ESLint检查。 解决方法:File=>Preferences=>Settings,然后在搜索框搜索vetur.validation.template,将vetur.validation.template从true改为false。
组件中我定义的data是如下的,但是,毫无作用。
data: { count: 0 }改成这样才有用
data: function () { return { count: 0 } }因为一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:否则就会出现其中一个组件修改了,其他组件也修改的事了。参考这里
如果想重构一下,觉得组件变得越来越复杂的时候改成这样
<div id="lordnb"> //删减了其他,只保留了key,并增加了post <lord-nb v-for="post in posts" v-bind:key="post.id" v-bind:post="post"></lord-nb> </div> Vue.component("lord-nb",{ props : { //增加一个post post : Object, id : Number, name : String, father : { type: Object, // 对象或数组默认值必须从一个工厂函数获取 default: function () { return { name: '黄帝' } } }, content : { type: String, default :'<span style=\'color:yellow\'>黄色</span>' } }, //template中所有属性增加前缀post. template :'<div class="blog-post"><h3>id:{{post.id}},name:{{post.name}},father:{{post.father.name}}</h3><div v-html="post.content"></div></div>' })然而此时,我发现了,浏览器会报错 Error in render: "TypeError: Cannot read property ‘name’ of undefined"
只有把father:{{ post.father.name }}改成father:{{father.name}}, 并且把
<lord-nb v-for="post in posts" v-bind:key="post.id" v-bind:post="post"></lord-nb>增加为
<lord-nb v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-bind:father="post.father"></lord-nb>时,错误提示才会去掉,且界面显示才正常。
具体原因不清楚,只因为我的这个father是对象?props一般好像支持值类型的比较多,对象一般用watch?我也不清楚,我初学者。
根据文中所说,大概意思就是说
Vue.component('good-title', { template : '<h3>标题</h3>', mounted: function () { console.log(this.$el.getAttribute('title-name')) } });如上所述,这里没props。然后在HTML中定义一个叫做title-name的属性,然后这个 title-name=“title” 特性就会自动添加到 的根元素上。
<good-title title-name="title"></good-title>但是这样其实并不会在控制台显示title。 必须增加
<div id="sss"> <good-title title-name="title"></good-title> </div> var sss = new Vue({ el : '#sss' })此时,才会调用console.log(this.$el.getAttribute('title-name'))控制台才会显示title。为什么用mounted,而我用created页面会报错,具体参考Vue生命周期中mounted和created的区别
之前都是各种事件相关的都在模板里就定义好了,但如果想从组件里控制子元素中的事件,或者说一个组件集合控制子组件中的事件。参考这里
<blog-post :style="{ fontSize: postFontSize + 'em' }" id="enlarge" v-bind:title="title" v-bind:content="content" v-on:click="postFontSize += 0.1"></blog-post> Vue.component('blog-post', { props: ['content','title'], template: ` <div class="blog-post"> <span>{{ title }}</span> <button> Enlarge text </button> <div v-html="content"></div> </div> ` }) var enlarge = new Vue({ el:'#enlarge', data :{ title : 'qwe', content : '<span>dasdadasd</span>', postFontSize: 1 } })然而按钮怎么点都没用,这是因为我们定义的元素是div,事件也被定义到这个div中,而按钮是div的子元素,这个事件应该被定义到这个button中。那么该怎么做呢? 子元素可以通过调用内建的 $emit 方法 并传入事件名称来触发一个事件。
//这里定义了v-on:enlarge-text替代了v-on:click <blog-post :style="{ fontSize: postFontSize + 'em' }" id="enlarge" v-bind:title="title" v-bind:content="content" v-on:enlarge-text="postFontSize += 0.1"></blog-post> //下面button用v-on:click="$emit('enlarge-text')"将enlarge-text这个事件传到父组件blog-post中 Vue.component('blog-post', { props: ['content','title'], template: ` <div class="blog-post"> <span>{{ title }}</span> <button v-on:click="$emit('enlarge-text')"> Enlarge text </button> <div v-html="content"></div> </div> ` }) var enlarge = new Vue({ el:'#enlarge', data :{ title : 'qwe', content : '<span>dasdadasd</span>', postFontSize: 1 } })v-model是一个指令,限制在<input>、<select>、<textarea>、components中使用,修饰符.lazy(取代 input 监听 change 事件)、.number(输入字符串转为有效的数字)、.trim(输入首尾空格过滤)。它其实是一个语法糖。
<input v-model="searchText">等价于
<input v-bind:value="searchText" v-on:input="searchText = $event.target.value" >那么在组件上怎么使用v-model呢? 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的event。
<my-input id="myinput" v-model="searchText" v-bind:label = "mylabel"></my-input> Vue.component("my-input",{ props : ['label','value'], template : ` <div>{{label}} <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)"> <p>{{ value }}</p> </div> ` }) new Vue({ el: '#myinput', data : { mylabel : '姓名', searchText : '' } })根据这里,我怎么也弄不出它的效果,实际只需要增加样式就够了。
<style> .demo-alert-box { padding: 10px 20px; background: #f3beb8; border: 1px solid #f09898; } </style>computed:计算属性一般在数据量比较大,比较耗时的情况下使用(例如搜索),只有虚拟dom与真实dom不同的情况下会执行computed;
method:方法使用,如果使用了其中一个方法,其他的方法都会被执行,比较耗时,不管虚拟dom与真实dom一不一样都会执行。
<div id="lord"> <p>{{ reversedMessageMethod() }}</p> <p>{{ reversedMessageComputed }}</p> </div> new Vue({ el: '#lord', data: data, methods:{ reversedMessageMethod: function () { return this.message1.split('').reverse().join('') } }, computed : { reversedMessageComputed: function () { return this.message2.split('').reverse().join('') } } })注意:computed中的属性不能与data中的属性同名,否则会报错。
区别:computed计算的结果如果不发生改变就不会触发result这个函数。而methods中一般都是定义的需要事件触发的一些函数。每次只要触发事件,就会执行对应的方法。如果把computed中的方法写到method中会浪费性能。computed必须返回一个值页面绑定的才能取得值,而methods中可以只执行逻辑代码,可以有返回值,也可以没有。