Vue - 計算されたプロパティとリスナー

目次

1. 計算された特性

1. 基本的な使い方

2. 複雑な使用法

3.ゲッターとセッター

4. プロパティとメソッドの比較

2、聞き手

1. 時計の使用方法


1. 計算された特性

1. 基本的な使い方

フルネームを取得するための変数、姓と名があります。

   <div id="app">

        <h2>您的firstname:{
   
   {firstName}}</h2>
        <h2>您的lastname:{
   
   {lastName}}</h2>
        
        <h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>

        <h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>

    </div>
    <script>
        Vue.config.productionTip = false;  //阻止 vue 在启动时生成生产提示。
        const vm = new Vue({
            el: '#app',
            data(){
                return{
                    firstName:'zhang',
                    lastName:'san'
                }
            },
            methods: {
                getFullName(){
                    return this.firstName + this.lastName
                }
            },
            computed:{//计算属性 一定要有一个返回值 在页面中渲染时是不需要加小括号的
                fullName(){
                    return this.firstName + this.lastName
                }
            }
        })
    </script>

  Mastache 構文を使用したスプライシング<h2>{ {firstName}}{ {lastName}}</h2>

  メソッドの使用方法<h2>{ {getFullName()}}</h2>

  計算されたプロパティの使用<h2>{ {fullName}}</h2>

この例では、計算された属性はメソッドと同じように見えますが、メソッド呼び出しでは () を使用する必要があるのに対し、計算された属性は使用しない点が異なります。通常、メソッドの名前は動詞で、計算された属性の名前は名詞です, しかし、これはあくまで基本的な使い方です。 

2. 複雑な使用法

   これで、多くのブック オブジェクトを含む配列データ ブックが作成されました。データ構造は次のとおりです。

本:[ 
          {id:110,name:"JavaScript の参入から参入まで",price:119}, 
          {id:111,name:"Java の参入から放棄まで",price:80}, 
          {id:112,name: "The Art ofcoding",price:99}, 
          {id:113,name:"Code Encyclopedia",price:150}, 
        ]

    すべての書籍の合計価格を計算する必要がありますtotalPrice

<div id="app">
			<h2>您的总价:{
   
   {totalPrice}}</h2>
		</div>
		<script>
			const vm = new Vue({
				el: '#app',
				data() {
					return {
						books: [{
								id: 110,
								name: "JavaScript从入门到入土",
								price: 119
							},
							{
								id: 111,
								name: "Java从入门到放弃",
								price: 80
							},
							{
								id: 112,
								name: "编码艺术",
								price: 99
							},
							{
								id: 113,
								name: "代码大全",
								price: 150
							},
						]
					}
				},
				computed: {
					/* totalPrice() {
						let total = 0
						for (let i = 0; i < this.books.length; i++) {
                              total += this.books[i].price
						}
						return total
					} */
					
					/* totalPrice() {
						let total = 0
						for (let index in this.books) {
							total += this.books[index].price
						}
						return total
					} */
					
					/* totalPrice() {
						let total = 0;
						for(let item of this.books){
							total += item.price
						}
						return total
					} */
					
					/* totalPrice() {
						let total = 0;
						this.books.forEach(item=>{
							total += item.price
						})
						return total
					} */
					
					/* map */
					/* totalPrice() {
						let total = 0;
						this.books.map(item=>{
							total += item.price
						})
						return total
					} */
					
					/* filter */
					/* totalPrice() {
						let total = 0;
						this.books.filter(item=>{
							total += item.price
						})
						return total
					} */
					
					/* reduce */
					/* totalPrice() {
						return this.books.reduce((total,item)=>{
							 return total + item.price 
						},0)
					} */
					
					/* totalPrice() {
						return this.books.reduce((total,item)=>total + item.price,0)
					} */
					
					/* some */
					totalPrice() {
						let total = 0;
						this.books.some(item=>{
							total += item.price
						})
						return total
					}
					
				}
			})
		</script>

各書籍オブジェクトの価格累積を取得します。いずれかの書籍の価格が変更されると、合計価格もそれに応じて変更されます。

3.ゲッターとセッター

計算プロパティには、実際には setter と getter の 2 つのメソッドがあります。

ただし、計算プロパティには一般に set メソッドがありません。読み取り専用プロパティには get メソッドのみがあります。ただし、上記では newValue は新しい値であり、set メソッドを使用して値を設定することもできますが、通常は使用できません。

       <div id="app">
			<input type="text" v-model="firstName"/><br>
			<input type="text" v-model="lastName"/><br>
			<input type="text" v-model="fullName"/>
			<!-- v-model实现数据的双向绑定 -->
			<!-- 2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
						备注:
								1.双向绑定一般都应用在表单类元素上(如:input、select等)
								2.v-model:value 可以简写为 v-model,因为v-model默认收集的就 
                                   是value值。 -->
		</div>
		<script>
			const vm = new Vue({
				el: '#app',
				data() {
					return {
						firstName: 'zhang',
						lastName: 'san'
					}
				},
				computed: { //计算属性 一定要有一个返回值 在页面中渲染时是不需要加小括号的
					/* fullName(){
						return this.firstName + this.lastName
					} */

					 fullName: {
						get: function() {
							return this.firstName +','+ this.lastName
						},
						set:function(val){
							var list = val.split(',')
							console.log(list);
							this.firstName = list[0]
							this.lastName = list[1]
						}
					} 
				}
			})
		</script>

 

 このようにして、計算されたプロパティの値を変更しながら、計算されたプロパティに関連付けられたプロパティの値も変更できます。

4. プロパティとメソッドの比較

       <div id="app">
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			<h2>您的fullname是从计算属性中得到:{
   
   {fullName}}</h2>
			
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
			<h2>您的fullname是从方法中得到:{
   
   {getFullName()}}</h2>
		</div>
		<script>
			const vm = new Vue({
				el:'#app',
				data(){
					return {
						firstName:'zhang',
						lastName:'san'
					}
				},
				methods:{
					getFullName(){
						console.log('这里调用了方法getFullName');
						return this.firstName + this.lastName
					}
				},
				computed:{//计算属性 一定要有一个返回值 在页面中渲染时是不需要加小括号的
					fullName(){
						console.log('这里调用了计算属性fullName');
						return this.firstName + this.lastName
					}
				}
			})
			
			/* 总结:计算属性的性能是优于方法的 因为计算属性是具有缓存特性的 */
		</script>

計算された属性にはキャッシュがあることがわかります。this.firstName + " " + this.lastName同じ属性の場合、メソッドは 4 回呼び出されますが、計算された属性は 1 回しか呼び出されません。計算された属性のパフォーマンスは明らかにメソッドよりも優れています。firstName を変更する場合、計算されたプロパティは 1 回だけ呼び出されますが、メソッドは 4 回呼び出す必要があります。

2、聞き手

1. 時計の使用方法

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Vue计算属性/侦听器/方法比较</title>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <h1>计算属性:computed</h1>
            {
   
   {fullName}}
            <h1>方法:methods</h1>
            {
   
   {fullName2()}}
            <h1>侦听器:watch</h1>
            {
   
   {watchFullName}}
            <h1>年龄</h1>
            {
   
   {age}}
        </div>
        <script>
            var other = 'This is other';
            var app = new Vue({
                el:"#app",
                data:{
                firstName:"zhang",
                lastName:"san",
                watchFullName:"zhangsan",
                age:18,
                },
                watch: {
                    firstName:function(newFirstName, oldFirstName){
                        console.log("firstName触发了watch,newFirstName="+newFirstName+",oldFirstName="+oldFirstName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    },
                    lastName:function(newLastName, oldLastName){
                        console.log("lastName触发了watch,newLastName="+newLastName+",oldLastName="+oldLastName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    }  
                },
                computed: {
                    fullName:function(){
                    console.log("调用了fullName,计算了一次属性")
                    return this.firstName+this.lastName+","+other;
                    }
                },
                methods: {
                    fullName2:function(){
                        console.log("调用了fullName,执行了一次方法")
                        fullName2 = this.firstName+this.lastName+","+other;
                        return fullName2;
                    }
                }
            });
        </script>
    </body>
    </html>

初期化:

 名/姓/両方を変更します

 計算で計算されない年齢を変更します

 Vue インスタンスの外部でオブジェクトを変更する

 Vue インスタンスの外側のオブジェクトを変更した後、Vue インスタンス内のオブジェクトを変更します。

テストの結論:

  1. fullName 属性は、computed を使用して計算され、値は firstName+lastName です。計算プロパティには缓存功能、firstName と lastName が変更されない場合、fullName は再計算されません。たとえば、age の値を変更した場合、fullName の値は再計算する必要がありません。
  2. メソッドにはキャッシュ機能がありません。たとえば、age の値を変更すると、fullName2() メソッドが再度実行されます。
  3. 関数が上記の 3 つの方法で実現できる場合、computed を使用する方が明らかに適切であり、コードが単純で、キャッシュ機能があります。
  4. 計算された属性のスコープは Vue インスタンス内にあり、Vue インスタンスの外部オブジェクトを変更してもレンダリングは再計算されませんが、Vue インスタンスの外部のオブジェクトが最初に変更され、次に Vue 計算された属性のオブジェクトが変更された場合、外部オブジェクトの値も再レンダリングされます。

計算されたプロパティ: 計算された

     Vue インスタンスの fullName 内の計算された属性範囲によって管理される firstName と lastName は通常、複数の変数をリッスンします。

リスナー:見てください

     データの変更を監視します。通常は変数または配列のみを監視します

使用するシーン

      watch( 异步场景)、computed( 数据联动) watch は監視データの後にメソッド名を文字列形式で直接追加できます。

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Vue计算属性/侦听器/方法比较</title>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <h1>计算属性:computed</h1>
            {
   
   {fullName}}
            <h1>方法:methods</h1>
            {
   
   {fullName2()}}
            <h1>侦听器:watch</h1>
            {
   
   {watchFullName}}
            <h1>年龄</h1>
            {
   
   {age}}
        </div>
        <script>
            var other = 'This is other';
            var app = new Vue({
                el:"#app",
                data:{
                firstName:"zhang",
                lastName:"san",
                watchFullName:"zhangsan",
                age:18,
                },
                watch: {
                    firstName:function(newFirstName, oldFirstName){
                        console.log("firstName触发了watch,newFirstName="+newFirstName+",oldFirstName="+oldFirstName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    },
                    lastName:function(newLastName, oldLastName){
                        console.log("lastName触发了watch,newLastName="+newLastName+",oldLastName="+oldLastName)
                        this.watchFullName = this.firstName+this.lastName+","+other
                    },
                    watchFullName:"change"

                },
                computed: {
                    fullName:function(){
                    console.log("调用了fullName,计算了一次属性")
                    return this.firstName+this.lastName+","+other;
                    }
                },
                methods: {
                    fullName2:function(){
                        console.log("调用了fullName,执行了一次方法")
                        fullName2 = this.firstName+this.lastName+","+other;
                        return fullName2;
                    },
                    change(){
                        console.log("调用了change,触发了watch")
                        return this.watchFullName='111'
                    }
                }
            });
        </script>
    </body>
    </html>

 ハンドラー メソッドは、通常のリスナーによってトリガーされるイベントと同等です。結果から、コンポーネントの初期化時には、リスナーにはハンドラー メソッドがないため、fullName には値がないことがわかります。

上記のコードを変更する場合、immediate: true を追加します。immediate: true は、ウォッチが宣言された後、ハンドラー内の関数がすぐに実行されることを意味します。対応するロジックを実行します。コンポーネントが初期化されると、リスナーはすぐにハンドラー メソッドをトリガーします。

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Vue计算属性/侦听器/方法比较</title>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
          <div>
            <p>FullName: {
   
   {person.fullname}}</p>
            <p>FirstName: <input type="text" v-model="person.firstname"></p>
          </div>
        </div>
        <script>
            var other = 'This is other';
            var app = new Vue({
              el: '#app',
               data(){
                return {
                    person: {
                        firstname: 'Menghui',
                        lastname: 'Jin',
                        fullname: ''
                    }
                }
              },
             watch: {
              person: {
                  handler(n,o){
                      this.person.fullname = n.firstname + '' + this.person.lastname;
                  },
                   immediate: true,  //刷新加载 立马触发一次handler
                  deep: true  // 可以深度检测到 person 对象的属性值的变化
              }
              }
            })
        </script>
    </body>
    </html>

入力ボックスにデータを入力すると、fullName の値が変わっていないことがわかりますが、これは、person.firstname の変更など、オブジェクトの内部プロパティ値の変更を Vue が検出できないためです。

したがって、現時点では、vue の深い監視 (deep) を使用する必要があります。

このとき、コード deep: true を追加します。

入力ボックスのデータが変更されるたびにフルネームが変更されることがわかります。

上記のことから、ハンドラーによって監視される新しい値は古い値と同じであることがわかります。これは、vue2.0 のピットヘジテーションと相同性によって引き起こされ、計算によって修復できます。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>

	</head>
	<body>
		<div id="app">
             <p>FullName: {
   
   {person.fullname}}</p>
             <p>FirstName: <input type="text" v-model="person.firstname"></p>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
		<script>
			const app = new Vue({
				el: "#app",
				data() {
					return {
						person: {
							firstname: 'Menghui',
							lastname: 'Jin',
							fullname: ''
						}
					}
				},
				methods: {

				},
				computed: {
                   person2(){
					    return JSON.parse(JSON.stringify(this.person));
				   }//解决深度监听新老值同源问题
				},
				watch:{
				   person2:{
					     handler(n,o){
							 console.log(this.person);
							 console.log(n.firstname);
					                 console.log(o.firstname);
							
							 /* this.person.fullname = this.person.firstname + this.person.lastname */
						 },
						/* immediate: true, */
						 deep: true  // 可以深度检测到 person 对象的属性值的变化
				   }
				}
			})
		</script>
	</body>
</html>

おすすめ

転載: blog.csdn.net/m0_46461853/article/details/126019079