vue干活

Vue总结(干货)

一、Vue的指令(指的是带有“v-”前缀的特殊属性)**

常见的Vue指令((v-if|v-else|v-else-if)/v-show/v-for/v-bind/v-on/v-if|v-else|v-else-if等等就不一一介绍了,下面讲解几个有意思的指令)

1)、v-pre

v-pre主要用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签。跳过大量没有指令的节点加快编译。

<div id="app">
<span v-pre>{{message}}</span>  //这条语句不进行编译
<span>{{message}}</span>
</div>

最终仅显示第二个span的内容

2)、v-cloak

这个指令是用来保持在元素上直到关联实例结束时进行编译。

{{message}}
在页面加载时会闪烁,先显示:
{{message}}
然后才会编译为:
hello world!

3)、v-once

     v-once关联的实例,只会渲染一次。之后的重新渲染,实例极其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。

This will never change:{{msg}} //单个元素

//有子元素

comment


{{msg}}



//组件

  • {{i}}


上面的例子中,msg,list即使产生改变,也不会重新渲染。

4)、v-model

这个指令用于在表单上创建双向数据绑定。

v-model会忽略所有表单元素的value、checked、selected特性的初始值。因为它选择Vue实例数据做为具体的值。

hello {{somebody}}

这个例子中直接在浏览器input中输入别的名字,下面的p的内容会直接跟着变。这就是双向数据绑定。

5)、事件修饰符

.stop 阻止事件继续传播

.prevent 事件不再重载页面

.capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理

.self 只当在 event.target 是当前元素自身时触发处理函数

.once 事件将只会触发一次

.passive 告诉浏览器你不想阻止事件的默认行为

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产

生。因此,用v-on:click.prevent.self会阻止所有的点击,

而 v-on:click.self.prevent 只会阻止对元素自身的点击。

<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>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

二、Vue模板

1)、文本

{{msg}}

2)、html

使用v-html指令用于输出html代码

3)、属性

HTML属性中的值应使用v-bind指令

4)、表达式

Vue提供了完全的JavaScript表达式支持

{{str.substr(0,6).toUpperCase()}}

{{ number + 1 }}

{{ ok ? ‘YES’ : ‘NO’ }}

<li v-bind:id="'list-' + id">我的Id是js动态生成的</li>
<html>
    <head>
        <meta charset="utf-8">
        <title>vue插值</title>
        <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
            </head>
            <body>
                <div id="app">
                    <ul>   
                        <li>
                            <h3>文本</h3>
                               {{msg}}
                        </li>
                        <li>
                            <h3>Html字符串渲染</h3>
                             <div v-html="htmlSter"></div>
                        </li>
                        <li>
                            <h3>v-bind属性绑定</h3>
                             <input type="text" value="18" />
                             <input type="text" v-bind:value="age" />
                        </li>
                        <li>
                            <h3>表达式</h3>
                               {{str.substr(0,6).toUpperCase()}}
                                       {{ number + 1 }}
                                       {{ ok ? 'YES' : 'NO' }}
                                       <li v-bind:id="'list-' + id">我的Id是js动态生成的</li>
                       </li>
                    </ul>
                </div>       
            </body>
            <script type="text/javascript">            
                new Vue({
                    el:'#app',
                    data:{
                        msg:'Hollo Vue!!!',
                        htmlSter:'<span style="color: red;">Html字符串渲染</span>',
                        age:20,
                        str:'https://www.baidu.com',
                        number:6,
                        ok:true,
                        id:16
                    }
                })        

1、 Mvvm定义MVVM是Model-View-ViewModel的简写。即模型-视图-视图模型。【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。总结:在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。MVVM流程图如下:

1. MVC的定义:MVC是Model-View- Controller的简写。即模型-视图-控制器。M和V指的意思和MVVM中的M和V意思一样。C即Controller指的是页面业务逻辑。使用MVC的目的就是将M和V的代码分离。‘MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。MVC和MVVM的区别并不是VM完全取代了C,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用。由于mvc出现的时间比较早,前端并不那么成熟,很多业务逻辑也是在后端实现,所以前端并没有真正意义上的MVC模式。而我们今天再次提起MVC,是因为大前端的来到,出现了MVVM模式的框架,我们需要了解一下MVVM这种设计模式是如何一步步演变过来的。

  1. 为什么会有MVVM框架?

在过去的10年中,我们已经把很多传统的服务端代码放到了浏览器中,这样就产生了成千上万行的javascript代码,它们连接了各式各样的HTML 和CSS文件,但缺乏正规的组织形式,这也就是为什么越来越多的开发者使用javascript框架。比如:angular、react、vue。浏览器的兼容性问题已经不再是前端的阻碍。前端的项目越来越大,项目的可维护性和扩展性、安全性等成了主要问题。当年为了解决浏览器兼容性问题,出现了很多类库,其中最典型的就是jquery。但是这类库没有实现对业务逻辑的分成,所以维护性和扩展性极差。综上两方面原因,才有了MVVM模式一类框架的出现。比如vue,通过数据的双向绑定,极大了提高了开发效率。

  1. MVVM框架:VUE的介绍

Vue就是基于MVVM模式实现的一套框架,在vue中:Model:指的是js中的数据,如对象,数组等等。View:指的是页面视图viewModel:指的是vue实例化对象为什么说VUE是一个渐进式的javascript框架, 渐进式是什么意思?1.如果你已经有一个现成的服务端应用,你可以将vue 作为该应用的一部分嵌入其中,带来更加丰富的交互体验;2.如果你希望将更多业务逻辑放到前端来实现,那么VUE的核心库及其生态系统也可以满足你的各式需求(core+vuex+vue-route)。和其它前端框架一样,VUE允许你将一个网页分割成可复用的组件,每个组件都包含属于自己的HTML、CSS、JAVASCRIPT以用来渲染网页中相应的地方。3.如果我们构建一个大型的应用,在这一点上,我们可能需要将东西分割成为各自的组件和文件,vue有一个命令行工具,使快速初始化一个真实的工程变得非常简单(vue init webpack my-project)。我们可以使用VUE的单文件组件,它包含了各自的HTML、JAVASCRIPT以及带作用域的CSS或SCSS。以上这三个例子,是一步步递进的,也就是说对VUE的使用可大可小,它都会有相应的方式来整合到你的项目中。所以说它是一个渐进式的框架。VUE最独特的特性:响应式系统VUE是响应式的(reactive),也就是说当我们的数据变更时,VUE会帮你更新所有网页中用到它的地方。关于这个响应式原理,官方已经讲得很清楚,不懂的同学,可以https://cn.vuejs.org/v2/guide/reactivity.html 查看。我们讲一下主流框架实现双向绑定(响应式)的做法:1. 脏值检查:angularangular.js是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,最简单的方式就是通过 setInterval() 定时轮询检测数据变动,当然Google不会这么low,angular只有在指定的事件触发时进入脏值检测,大致如下:DOM事件,譬如用户输入文本,点击按钮等。( ng-click ) XHR响应事件 ( $http ) 浏览器Location变更事件 ( $location ) Timer事件( $timeout , $interval ) 执行 $digest() 或 $apply()在 Angular 中组件是以树的形式组织起来的,相应地,检测器也是一棵树的形状。当一个异步事件发生时,脏检查会从根组件开始,自上而下对树上的所有子组件进行检查,这种检查方式的性能存在很大问题。2.观察者-订阅者(数据劫持):vueObserver 数据监听器,把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty()方法把这些属性全部转成setter、getter方法。当data中的某个属性被访问时,则会调用getter方法,当data中的属性被改变时,则会调用setter方法。Compile指令解析器,它的作用对每个元素节点的指令进行解析,替换模板数据,并绑定对应的更新函数,初始化相应的订阅。Watcher 订阅者,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。Dep 消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法。执行流程如下:

从图中可以看出,当执行 new Vue() 时,Vue 就进入了初始化阶段,一方面Vue 会遍历 data 选项中的属性,并用 Object.defineProperty 将它们转为 getter/setter,实现数据变化监听功能;另一方面,Vue 的指令编译器Compile 对元素节点的指令进行解析,初始化视图,并订阅Watcher 来更新视图, 此时Wather 会将自己添加到消息订阅器中(Dep),初始化完毕。当数据发生变化时,Observer 中的 setter 方法被触发,setter 会立即调用Dep.notify(),Dep 开始遍历所有的订阅者,并调用订阅者的 update 方法,订阅者收到通知后对视图进行相应的更新。因为VUE使用Object.defineProperty方法来做数据绑定,而这个方法又无法通过兼容性处理,所以Vue 不支持 IE8 以及更低版本浏览器。另外,查看vue原代码,发现在vue初始化实例时, 有一个proxy代理方法,它的作用就是遍历data中的属性,把它代理到vm的实例上,这也就是我们可以这样调用属性:vm.aaa等于vm.data.aaa。好了,关于mvvm设计模式及vue的双向绑定原理就讲到这。

四、spa原理

写在前面:通常 SPA 中前端路由有2种实现方式:

window.history
location.hash
下面就来介绍下这两种方式具体怎么实现的

一.history

1.history基本介绍

window.history 对象包含浏览器的历史,window.history 对象在编写时可不使用 window 这个前缀。history是实现SPA前端路由是一种主流方法,它有几个原始方法:

history.back() - 与在浏览器点击后退按钮相同
history.forward() - 与在浏览器中点击按钮向前相同
history.go(n) - 接受一个整数作为参数,移动到该整数指定的页面,比如go(1)相当于forward(),go(-1)相当于back(),go(0)相当于刷新当前页面
如果移动的位置超出了访问历史的边界,以上三个方法并不报错,而是静默失败
在HTML5,history对象提出了 pushState() 方法和 replaceState() 方法,这两个方法可以用来向历史栈中添加数据,就好像 url 变化了一样(过去只有 url 变化历史栈才会变化),这样就可以很好的模拟浏览历史和前进后退了,现在的前端路由也是基于这个原理实现的。

2.history.pushState

pushState(stateObj, title, url) 方法向历史栈中写入数据,其第一个参数是要写入的数据对象(不大于640kB),第二个参数是页面的 title, 第三个参数是 url (相对路径)。

stateObj :一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null。
title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。
url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。
关于pushState,有几个值得注意的地方:

  pushState方法不会触发页面刷新,只是导致history对象发生变化,地址栏会有反应,只有当触发前进后退等事件(back()和forward()等)时浏览器才会刷新

  这里的 url是受到同源策略限制的,防止恶意脚本模仿其他网站 url用来欺骗用户,所以当违背同源策略时将会报错

3.history.replaceState

    replaceState(stateObj, title, url) 和pushState的区别就在于它不是写入而是替换修改浏览历史中当前纪录,其余和 pushState一模一样

4.popstate事件

定义:每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。

注意:仅仅调用pushState方法或replaceState方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。

用法:使用的时候,可以为popstate事件指定回调函数。这个回调函数的参数是一个event事件对象,它的state属性指向pushState和replaceState方法为当前URL所提供的状态对象(即这两个方法的第一个参数)。

5.history实现spa前端路由代码

a.html
b.html

// 注册路由
document.querySelectorAll(’.api’).forEach(item => {
item.addEventListener(‘click’, e => {
e.preventDefault();
let link = item.textContent;
if (!!(window.history && history.pushState)) {
// 支持History API
window.history.pushState({name: ‘api’}, link, link);
} else {
// 不支持,可使用一些Polyfill库来实现
}
}, false)
});

// 监听路由
window.addEventListener('popstate', e => {
  console.log({
    location: location.href,
    state: e.state
  })
}, false)
   popstate监听函数里打印的e.state便是history.pushState()里传入的第一个参数,在这里即为{name: 'api'}

二.Hash

1.Hash基本介绍

url 中可以带有一个 hash http://localhost:9000/#/a.html

window 对象中有一个事件是 onhashchange,以下几种情况都会触发这个事件:

直接更改浏览器地址,在最后面增加或改变#hash;
通过改变location.href或location.hash的值;
通过触发点击带锚点的链接;
浏览器前进后退可能导致hash的变化,前提是两个网页地址中的hash值不同。
2.Hash实现spa前端路由代码

// 注册路由
document.querySelectorAll(’.api’).forEach(item => {
item.addEventListener(‘click’, e => {
e.preventDefault();
let link = item.textContent;
location.hash = link;
}, false)
});
// 监听路由
window.addEventListener(‘hashchange’, e => {
console.log({
location: location.href,
hash: location.hash
})
}, false)

五、Vue的插槽(slot)

slot 插槽 ,是用在组件中,向组件分发内容。它的内容可以包含任何模板代码,包括HTML。

vue 在 2.6.0 中,具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍有用的特性。但是将会在vue 3 中,被废弃的这两个,不会被支持即无效。

在 2.6.0之前,插槽的用法:

  1. 匿名插槽。

以 .vue 这种单文件模块为例

//创建 testSlot.vue组件


     //slot里面也可以设置内容,这个可以设置不传内容时,slot有个默认值替换
这里面是slot的默认值

子组件页面



//引用testSlot组件


引用testSlot组件的页面



{{msg}}


注意事项:

1) 匿名的方式,就是指把在引用组件的时候,里面传的内容,全部一起传送到组件页面中 所在的位置。

2) 只要组件中有 ,并且不管有多少个,都会全部渲染为传过来的内容。

3) 里面也可以设置内容,这个内容是保证引入组件的时候,有个默认值。当 然,里面不设置内容也可以,这样只是没有默认值,是不会报错的。

4) 传递的内容,也可以是动态的,如同上面一样。但是要注意的是,这个内容不能是 引用组件的时候组件上的内容,要注意作用域。可以查看官网 插槽编译作用域。

5) 如果传递的内容,没有slot 来接收,那么,传递的内容就会被抛弃掉,不会起作用。

6) 那这个时候,如果我想某个 传指定的 内容呢?那这个时候就需要具名插槽了。

  1. 具名插槽,就是给插槽指定名称,然后 一 一对应

//引入组件的页面


------------header----------------


这是header1的内容


这是header2的内容


<template slot='footer'>
    <p>------------footer----------------</p>
    <h3>这是footer1的内容</h3>
    <p>这是footer2的内容</p>
</template>
    
<p>-----------default-----------------</p>
<p>这是default剩下的内容1</p>
<p>这是default剩下的内容2</p>

//组件当前页面
—默认内容—

slot组件页面

---header的默认内容--- ---footer的默认内容--- 注意事项

1) 引入组件的页面,如果是多个内容,需要用template 包裹起来,并且添加 slot 属性和 自定义值 。

2) slot 的值 需要和 组件中 name的值相对应。

3) 如果剩下的内容没有包裹起来并制定值的话,那么这些内容会被渲染到 组件中 所有的 所在的位置。

4) 如果 slot 设置为default 和 name 设置为default,那就和没设置slot与name是一样的。

5) 和vue 2.6.0 以后的具名插槽相比 template上的 slot=‘xxx’ 只需要 改成 v-slot : xxx 就行了,等号改成了冒号,并且值没有引号,带引号反而会报错。

6) 具名插槽只需要 name值 与 slot的值 对应 ,插槽的顺序是没有关系的。

  1. slot-scope 作用域插槽。

    这个的作用,主要就是当向组件发送的内容需要和组件的props属性的内容有联系时,才使用这个作用域插槽。简单点来说就是:可以使用 子组件的数据 和 父组件传过来的props的值。

//引入组件的页面





说了:{{thing.said}}



{{val.send.text}}





//组件页面





    <ul>
        <li v-for='item in list' :key='item.id'>{{item.text}}</li>
    </ul>
</div>

注意事项:

1) 作用域插槽主要是 使用子组件的任何数据 来达到自定义显示内容的目的

2) 作用域插槽最最最最最重要的一步,即是在 上绑定数据 ,如果没有绑定数据,则父组件收到的,只是一个空对象{ }。

3) 作用域插槽中 上绑定数据,可以是写死的,也可以是动态绑定的。如果是动态绑定的,则也需要 v-bind:xxx

4) 作用域插槽中 上绑定的数据 也可以传一个定义好的有返回值的 mthods 方法。比如我定义了 ,然后say方法为:say:function(){ return ‘我说了’ } 。最后得到的结果就是 “我说了”,当然,动态绑定一定要加 v-bind:xxx。

5) 当 绑定上数据之后,引用组件的地方 中 发送的内容就能通过 slot-scope 来获取。获取到的内容,就是一个对象,比如 我这里绑定 said=‘message’ 之后, 那边接收到的就是 { said:“xxxx”} 一个对象。

6) slot-scope 可以接收任何有效的可以出现在函数定义的参数位置上的 JavaScript 表达式。

vue 2.6.0之后 v-slot 只能用在 组件component 或者 template 上 ,用在 div 或 p 这种标签上是会报错的

  1. 具名插槽的变化

------------header----------------

这是header1的内容

这是header2的内容

<!--2.6.0之后的写法-->
<template v-slot:header>
    <p>------------header----------------</p>
    <h3>这是header1的内容</h3>
    <p>这是header2的内容</p>
</template>
1) slot=' xxx ' 改成了 v-slot : xxx 并且冒号后面这个名称不能打引号

2) 组件页面中slot的内容没有变化

3) 2.6.0 之后 具名插槽 v-slot:header 可以缩写为 #header ,必须是有参数才能这样写!!! # = "xxx " 这样是不行的 #default = ‘xxx’ 这样才可以

  1. 作用域插槽的变化
说了:{{thing.said}}
<template slot='listbox' slot-scope='value'>
    <p>{{value.send.text}}</p>
</template>


<!--2.6.0之前的写法,不能单独用在html标签上-->
<template v-slot:sayWhat='thing'>
  <div>说了:{{thing.said}}</div>
</template>
<template v-slot:listbox='value'>
    <p>{{value.send.text}}</p>
</template>

1) 两个属性合并成了一个 v-slot : 插槽名称 = ’ 传过来的值 ’ 。

2) 组件页面中slot的内容没有变化 。

3) v-slot 不能用在 html 标签上 。

4) 如果是默认插槽 可以写成 v-slot=‘xxx’。

5) 还增加了 可以解构插槽props 和 设置默认值的内容,具体的可以查看官网 解构插槽

  1. 新增的还有 动态插槽名

什么是动态插槽名?大致就是动态指令参数也可以用在v-slot上,这个就要涉及到2.6.0新增的 动态参数

<template v-slot:[attrContent]=‘msg’>

xxx
这个 attrContent 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。 比如这里attrContent 最终的值为 default 则渲染出来的结果 就是 v-slot:default='msg' 。

注意:

1) 单独在 [ ] 方括号中也可以使用表达式,但是不能存在引号和空格

2) 当然 这个动态的值 可以通过 方法,计算属性,或者 data数据 里面的内容。重要的是这个动态的值 是 引用组件的 作用域。简单点说就是父级组件的作用域。

例如,上面 v-slot:sayWhat=‘thing’ 可以写成:

1) v-slot:[first+sec]=‘thing’ 注意 加号两边不能留空格

2) v-slot:[attr]='thing'

3) v-slot:[attrs]='thing'

4) v-slot:[getattr()]='thing'
export default{
    data () {
        return {
            msg: '这是动态传入的slot的内容',
            attr:'sayWhat',
            first:'say',
            sec:'What',
        }
    },
    components:{ slotScope },
    computed:{
        attrs:function(){
            return 'sayWhat'
        }
    },
    methods:{
        getattr(){
            return 'sayWhat'
        }
    }
}

六、Vue的watch的用法

在vue中,使用watch来响应数据的变化。watch的用法大致有三种。下面代码是watch的一种简单的用法:

<input type="text" v-model="cityName"/>
new Vue({
  el: '#root',
  data: {
    cityName: 'shanghai'
  },
  watch: {
    cityName(newName, oldName) {
      // ...
    }
  } 
})

直接写一个监听处理函数,当每次监听到 cityName 值发生改变时,执行函数。也可以在所监听的数据后面直接加字符串形式的方法名:

watch: {
cityName: ‘nameChange’
}
}

immediate和handler

 这样使用watch时有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。

  比如当父组件向子组件动态传值时,子组件props首次获取到父组件传来的默认值时,也需要执行函数,此时就需要将immediate设为true。
new Vue({
  el: '#root',
  data: {
    cityName: ''
  },
  watch: {
    cityName: {
      handler(newName, oldName) {
        // ...
      },
      immediate: true
    }
  } 
})

监听的数据后面写成对象形式,包含handler方法和immediate,之前我们写的函数其实就是在写这个handler方法;

immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。

deep

当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。

<input type="text" v-model="cityName.name"/>
new Vue({
  el: '#root',
  data: {
    cityName: {id: 1, name: 'shanghai'}
  },
  watch: {
    cityName: {
      handler(newName, oldName) {
      // ...
    },
    deep: true,
    immediate: true
    }
  } 
})

设置deep: true则可以监听到cityName.name的变化,此时会给cityName的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。如果只需要监听对象中的一个属性值,则可以做以下优化:使用字符串的形式监听对象属性:


watch: {
    'cityName.name': {
      handler(newName, oldName) {
      // ...
      },
      deep: true,
      immediate: true
    }
  }

这样只会给对象的某个特定的属性加监听器。

数组(一维、多维)的变化不需要通过深度监听,对象数组中对象的属性变化则需要deep深度监听。

Vue的vuex

只要来读取的状态集中放在store中;改变状态的方式就是提交mutations。这是个同步的实物;异步逻辑应该封装中action中。

在main.js引入store,注入。新建一个目录store,…export。

场景有: 单页面应用,组件之间的状态,音乐播放,登录状态,加入购物车

state

Vuex 使用单一状态树,既每个应用将仅仅包含一个store实例,单单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。

mutations

mutations定义的方法动态修改Vuex的store中的状态或数据。

getters

类似vue的计算属性,主要用来过滤一些数据。

action

action可以理解为通过mutations里面处理数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view层通过store.dispath来分配action。

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    increment(context) {
      context.commit('increment')
    }
  }
})

modeules

项目特别复杂的时候,可以让每一个模块拥有自己的state,mutation,action,getters,使得结构非常清晰,方便管理


  const modulesA = {
    state: { ... },
    mutations: { ... },
    actions: { ... }
    }
  }


  const modulesB = {
    state: { ... },
    mutations: { ... },
    actions: { ... }
    }
  }


const store = new Vuex.store({
  modules: {
    a: modulesA,
    b: modulesB
  }
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值